WPF Stack Panel Align Centrally - c#

I want to be able to align buttons within a stack panel centrally. The number of buttons is dynamic and generated when the control is loaded.
For example, if 1 button is generated then this button should be placed in the center of the control. If 5 buttons are displayed then all 5 should be horizontally aligned next 2 each other but central to the control.
An alternative approach would be to have the control dynamically resize based on its content so it would be wider with more buttons and then horizontally align the user control on the page but I'm not sure how to approach either solution?
Does anybody have any ideas?

This should work. Set the Horizontal Alignment in the stack panel, and make sure when you are dynamically adding your button, you give them each a margin property value to give them some space from each other. horizontal to each other, central to the control.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="20">
<Button Margin="10">one</Button>
<Button Margin="10">two</Button>
<Button Margin="10">three</Button>
<Button Margin="10">four</Button>
<Button Margin="10">five</Button>
</StackPanel>

You can simply set following in XAML
StackPanel.HorizontalAlignment = HorizontalAlignment.Center;
or
HorizontalAlignment="Center" (as GrayFox374 mentioned)
Here is a MSDN sample explaining various alignment operations, having exactly what you need I think -
How to: Horizontally or Vertically Align Content in a StackPanel

Related

WPF Scrolling AutoSizing Panel

I have a WPF application in which the main window holds a DockPanel with two children. The top child is another DockPanel which holds the menu and is of a fixed size. The lower child is the main work area, which should fill the remaining space and be resizable along with the window. (Hence the DockPanel parent.) Draggable objects get placed in this work area and might appear anywhere inside it.
I'm trying to figure out how to make scroll bars appear if an object is dragged outside the visible area.
The approximate XAML structure currently goes
<Window>
<DockPanel>
<DockPanel with fixed-size content ... >
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid ClipToBounds="True" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</ScrollViewer>
</DockPanel>
</Window>
So far I've tried a Grid and a Canvas. Both have built-in scroll bars, but they won't appear unless dimensions are specified--but if I apply dimensions, then the panel won't automatically resize to fill the work area.
Then I tried surrounding the panel with a ScrollViewer. The unconstrained panel now successfully auto-resizes to fill the space, but the ScrollViewer has the same problem as the panel--it will only display scroll bars if it's constrained to hard dimensions.
I'm thinking that this would work if I could dynamically constrain the ScrollViewer. So far, I haven't found any reliable way to dynamically apply size values to the ScrollViewer.
Is there a way to create a Binding between the ScrollViewer dimensions and the ActualHeight and ActualWidth of the Grid? Or, is there a way I can define the ActualHeight/ActualWidth of the grid as a DynamicResource that can be applied to the ScrollViewer? Or is there some other panel or method or resource that can be used so that all three criteria (panel fills available space, panel auto-resizes with window, anything dragged outside visible area triggers scroll bars) are met?
Thanks in advance for any help.
The problem was that I did not have a DockPanel.Dock setting on the bottom child of the containing DockPanel. Relying on the DockPanel's LastChildFill wasn't enough to do the job. Once I set DockPanel.Dock = Bottom on the bottom child, the scroll bars started working.

Let a label stay in the foreground

I have multiple images that have labels (the UI element) in the bottom right corner. At creation, I first load the images and then the labels, so that the labels are in the foreground (visible). At runtime the order of the images changes - they are repositioned on my Grid. As a result, Labels aren't visible if the image was repositioned, because the Label was created earlier and is therefore behind the image.
Now how do I force the label to stay on top without recreating the labels?
Regards
Try set Canvas.ZIndex = 1 to Label
Like:
this.labelName.SetValue(Canvas.ZIndexProperty, 1);
or in XAML:
<sdk:Label Canvas.ZIndex="1" Content="My Text"/>

I'm having trouble positioning elements in a Grid when the window is resized

I have a 50x50 draggable grid inside another grid that I am able to move around with the cursor. (I forgot that I am using the DraggableExtender class
The problem is that I want the moveable grid to be relatively positioned inside it's container grid no matter how the container grid is resized. My solution right now is to dynamically change the HorizontalAlignment and VerticalAlignment of the moveable grid whenever it is moved, but this is hacky and doesn't work well.
Relative positioning in a grid is one of the easiest things to do in XAML, but not when you have draggable elements ;(
Any ideas?
EDIT for code and images:
My XAML:
<Grid Margin="10" ClipToBounds="True" Background="#FFB4B4B4">
<Grid Name="testGrid" MouseLeftButtonDown="testGrid_MouseLeftButtonDown" MouseLeftButtonUp="testGrid_MouseLeftButtonUp" RenderTransformOrigin="0.5,0.5" Height="100" Margin="50,0,0,0" Width="100" Background="#FFE6E6E6" local:DraggableExtenderGrid.CanDrag="true" HorizontalAlignment="Center"/>
</Grid>
and I use a DraggableExtender class (shown here) which I have edited to apply to a Grid instead of a Canvas (I was hoping for better results from a grid.. but both containers produce the same result, even with the original class on a canvas).
This is a picture of my 2 grids. I can move the smaller grid around inside it's parent grid, but I would like for it to maintain relative positioning once the window is resized. This is what it currently looks like when I resize the window. In this particular example, the grid would ideally remain slightly off-center horizontally and vertically in both pictures.
May be you should try placing the Grid inside a Canvas instead..
Take a look here

Why StackPanel does not stretch its children vertically?

(new to WPF) I am looking over the WPF example:
<Window x:Class="Attempt_XAML.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Label HorizontalAlignment="Center">A Button Stack</Label>
<Button HorizontalAlignment="Left">Button 1</Button>
<Button HorizontalAlignment="Right">Button 2</Button>
<Button Background="#FFA29494">Button 3</Button>
<Button>Button 4</Button>
</StackPanel>
</Window>
Remark in MS notes that:
The default value is stretch for both HorizontalAlignment and
VerticalAlignment of content that is contained in a StackPanel.
However, result looks different from what I am expecting. Button and Label are not stretched out vertically, but only horizontally(i.e they don't fill the entire space of Window in both directions) Why ?
Button and Label are not stretched out vertically, but only horizontally(i.e they don't fill the entire space of Window in both directions) Why ?
To understand the reason, you really need at least a basic understanding of Panels. Any Panel such as a StackPanel uses a measure-arrange cycle to decide on a layout for its child elements:
in the "measure" cycle, it assigns a size to each child
in the "arrange" cycle, it positions each child in its view
The key feature of a StackPanel is that it has infinite space -- infinite horizontal space if its orientation is Horizontal, and infinite vertical space if Vertical. In other words, it does not actually pay attention to the size available to it (in the direction of its orientation), but claims an infinite space. So therefore, coming back to your example, even though the VerticalAlignment of the children may be Stretch, they cannot actually be stretched out to an infinite size.
If you need a panel that stretches out its children to fill the available space, then Grid is a good example (by default the Grid will assign an equal share of the total height to each child -- or you can use the star sizing to adjust the proportions). You could also consider creating your own custom Panel, if you need a specialized layout behavior.
Edit
To clarify "infinite space": what I mean is that the StackPanel tells its children that there is infinite space available. What do you do if you are a Button, Label, etc, and there is infinite space available? You probably just take up the minimum space you need, even if your VerticalAlignment is "Stretch", right? That's what happens. Contrast to a Grid, which tells the child controls that they have x (finite) amount of space -- in that case, a Button, Label, etc, will fill up all that space (if their VerticalAlignment is "Stretch").
To illustrate the above, take this custom control as an example:
public class TestControl : ContentControl
{
public string Description { get; set; }
protected override Size MeasureOverride(Size availableSize)
{
System.Diagnostics.Debug.WriteLine("Size available for '" + Description + "': " + availableSize.Height);
return base.MeasureOverride(availableSize);
}
}
This doesn't actually do anything, just reports how much space has been allocated to it. Now, place the test control in a Grid and a StackPanel, and compare:
<Grid Height="50">
<Grid.RowDefinition />
<Grid.RowDefinition />
<local:TestControl Description="in Grid" />
<StackPanel Grid.Row="1" Height="10">
<local:TestControl Description="in StackPanel" />
</StackPanel>
</Grid>
You'll see that the Grid assigns its CustomPanel (the first one above) a height of 25 (half its height). The StackPanel, though, assigns its CustomPanel a height of Infinity.
Although default value is stretch for both HorizontalAlignment and VerticalAlignment of Content that is contained in a StackPanel. But in which direction to stretch is controlled by Orientation Property.
If Orientation is set to Vertical then all the items of the stack with no defined width value are stretched only.

How to stop ScrollViewer from scrolling down

I need to make the ScrollViewer to only scroll down.
I have created a scrollviewer in Xaml and have populated it with a stackpanel full of rectangles in code. I then start the user at the bottom and want them to use a "walking" motion with their fingers (like a bass player) to scroll to the top but do not want them to be able to scroll back to the bottom.
My Xaml looks like this:
<ScrollViewer Height="730" HorizontalAlignment="Left" Margin="6,6,0,0" Name="scrollViewer1" VerticalAlignment="Bottom" Width="462">
<StackPanel Name="TrackStackPanel">
</StackPanel>
</ScrollViewer>
But since it is filled in code, need to accomplish as much as I can in code.
I would try disabling vertical scrolling via VerticalScrollBarVisibility="disabled" - handle the gestures, then scroll accordingly by setting [ScrollToVerticalOffset].
If this does not work, try placing a layer (a Grid for example) above your ScrollViewer, so that it will receive all the gestures, then do as above, scroll via ScrollToVerticalOffset.

Categories

Resources