WrapPanel not wrapping when in a StackPanel with Horizontal orientation - wpf

The labels in the example below (WPF/XAML) just parade off the screen, no wrapping occurs. Removing the orientation works, but doesn't provided the needed functionality/look & feel. Any ideas how to make the WrapPanel wrap to the current size of the StackPanel?
<Window Height="300" Width="600">
<StackPanel Orientation="Horizontal">
<WrapPanel>
<Label Height="28" Name="label1" Width="120">First Name</Label>
<Label Height="28" Name="label2" Width="120">John</Label>
<Label Height="28" Name="label3" Width="120">Last Name</Label>
<Label Height="28" Name="label4" Width="120">Smith</Label>
<!-- ...more labels!... -->
</WrapPanel>
<!-- ...other controls/panels... -->
</StackPanel>
</Window>

You can bind the WrapPanel's MaxWidth to the StackPanel's ActualWidth.
I haven't tried this, but basically:
<WrapPanel MaxWidth="{Binding ActualWidth, ElementName=myStackPanel}"/>

What you're doing isn't possible because of the algorithm that StackPanel uses when doing horizontal layout. It's basically going to ask each child element how big it wants to be and however much space it asks for it's going to give it.
You would either need to:
Set a Width or MaxWidth on the WrapPanel.
Use a WrapPanel as the outer panel in place of the StackPanel.

Related

Cannot align label in stackpanel

I'm not a wpf expert, so maybe the problem is really simple than appear. Anyway, I made a stackpanel with this structure:
<StackPanel Orientation="Horizontal">
<Label Content="Match" FontWeight="Bold"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</StackPanel>
How you can see I set the orientation to horizontal so I can have both label in the same row. I need also to align the second label "Foo" to right. I tried setting the HorizontalAlignment property, but, the label is stuck on the same position. What I can do for fix this?
The simplest answer is that you can't.
Stackpanel is made to stack things after each other.
You can do it either vertically of horizontally and you can align the stackpanel to the right or left but you cannot align the items inside it.
You can use Grid or another container instead.
<Grid>
<Label Content="Match" FontWeight="Bold" HorizontalAlignment="Left"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</Grid>
StackPanel does not support the individual alignment of the child controls. However you can set the alignment of the whole stackpanel. However its not the case here.
What you can do is put your labels in a Uniform Grid of 1 row and 2 columns.
<UniformGrid Rows="1" Columns="2">
<Label Content="Match" FontWeight="Bold"/>
<Label Content="Foo" HorizontalAlignment="Right"/>
</UniformGrid>

Synchronizing parent height to child height in WPF

I'm developping with VS 2015 and WPF a mask designer, in which i can drag, move and resize controls.
One of These controls is a Label which has a TextBlock as Content.
This looks in my XAMl like that:
<Label Background="AliceBlue" HorizontalAlignment="Left" Margin="10,5,0,0" VerticalAlignment="Top">
<TextBlock TextWrapping="Wrap" Height="Auto">Label</TextBlock>
</Label>
For the TextBlock i have set TextWrapping to "Wrap" and Height to "Auto".
When i try to resize the height of the Label at it's allowed minimum, the content of the TextBlock shall still be completely visible.
I tried this with a TextBlock and it worked.
But when i try it with a Label implementing a TextBlock it doesn't work, the content of the TextBlock isn't completely visible anymore.
How can i synchronize the parent's height to the child's height?
Thanks in advance!
Patrick
You can use the Name of parent and bind its ActualHeight
<Label x:Name="parentElementName" Background="AliceBlue" HorizontalAlignment="Left" Margin="10,5,0,0" VerticalAlignment="Top">
<TextBlock TextWrapping="Wrap" Height="{Binding ActualHeight, ElementName=parentElementName}">Label</TextBlock>
</Label>
Edit
<Label x:Name="parentElementName" Background="AliceBlue" Height="{Binding ActualHeight, ElementName=Child}"HorizontalAlignment="Left" Margin="10,5,0,0" VerticalAlignment="Top">
<TextBlock x:Name="Child" TextWrapping="Wrap" Height="Auto">Label</TextBlock>
</Label>
#Ghassen's answer is basically correct. If you want to bind the parent to the child then reverse the answer above. The reversed code is shown below.
<Label x:Name="ParentLabel" Height="{Binding ElementName=ChildBlock, Path=ActualHeight}" Width="{Binding ElementName=ChildBlock, Path=ActualWidth}" Background="Blue">
<TextBlock x:Name="ChildBlock" Height="100" Width="100" Background="Green"></TextBlock>
</Label>

Having issues with the scroll bar in WPF

So im trying to get my scroll bar to A only show up as needed and B show up only around my description text
Right now the scroll view is going from the top of the window to the bottom
<Window x:Class="WpfApplication3.DataWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataWindow" Height="300" Width="300">
<Grid>
<Label x:Name="lblTitle" Content="Label" HorizontalAlignment="Left" Margin="96,25,0,0" VerticalAlignment="Top" Width="186"/>
<Label x:Name="lblPublishDate" Content="Label" HorizontalAlignment="Left" Margin="96,53,0,0" VerticalAlignment="Top" Width="186"/>
<Image x:Name="imgPic" HorizontalAlignment="Left" Height="81" Margin="10,10,0,0" VerticalAlignment="Top" Width="81"/>
<ScrollViewer>
<TextBlock x:Name="tbDesc" HorizontalAlignment="Left" Margin="10,96,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="167" Width="272" Text="TextBlock" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" />
</ScrollViewer>
</Grid>
A grid tries to let it's children take up all availble space.
Your ScrollViewer is one of the children, so it will fill all available space by default.
There are a number of ways around this.
You could use a different panel type, one that doesn't try to stretch it's children to fill all available space. Based on what you're doing with excessively large margins, a Canvas might be suitable.
I would suggest reading this for a quick understanding of WPF's available Layout Panels : WPF Layouts - A Visual Quick Start
Another alternative is to give your Grid some Row Definitions, and specify that the row containing the ScrollViewer should be of a fixed size, or should be sized so it fits whatever size the child object wants (Height="Auto")
Or you could give your ScrollViewer a fixed height, and set it's VerticalAlignment property so it gets docked to either the top or bottom of the Grid.
Personally I would recommend the first option - reviewing WPF's layout system and determining a more approrpiate panel type for your layout. And if the most appropriate panel type is a Grid, then I would highly recommend using the RowDefinitions and ColumnDefinitions to give your Grid some structure, rather than trying to use excessively large Margins to position your controls.
You're pretty close, the problem appears to be an issue of layout. Because the controls are arranged in the grid without row and column definitions the scrollviewer is attempting to resize to the full size of the grid while the textblock is adhereing to its fixed size and margin. Try the following starting point and see if it helps:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<Label x:Name="lblTitle" Content="Label" HorizontalAlignment="Left" Width="186"/>
<Label x:Name="lblPublishDate" Content="Label" HorizontalAlignment="Left" Width="186"/>
<Image x:Name="imgPic" HorizontalAlignment="Left" Height="81" Width="81"/>
</StackPanel>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="tbDesc" HorizontalAlignment="Left" TextWrapping="Wrap" Text="TextBlock"/>
</ScrollViewer>
</Grid>

VerticalAlignment="Stretch" for label inside canvas doesn't work

How to use VerticalAlignment="Stretch" with a Label inside a Canvas? I'm trying to center the text "Cancel" in the button as in the code below. To use fixed height and width for the label isn't a desired option.
<Button Name="buttonCancel" Width="80" Height="40" IsCancel="True" Padding="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Canvas>
<Label Canvas.Top="0" Canvas.Left="0" Padding="0" FontSize="10">Esc</Label>
<Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">Cancel</Label>
</Canvas>
</Button>
Use a binding to the Canvas's ActualWidth:
<Canvas>
<Label Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}, Path=ActualWidth}">...</Label>
</Canvas>
But as mentioned above, if you are interested in dynamic stretching layouts, the Canvas is not the ideal choice of control.
A Canvas does not perform any scaling layout of its contents; if you want to scale the contents, you could use Grid in this case, which will, by default, scale both Label elements to fill the Content space.
Assuming you need the canvas for other objects that are of a fixed nature, you could overlay the Canvas on a Grid, and then put the labels in the grid. You can put the labels before the canvas to make them background z-index (overwritten by canvas objects) or after the canvas to make them higher z-index (will overwrite canvas objects). For example:
<Button Name="buttonCancel" Width="80" Height="40" IsCancel="True" Padding="0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Grid>
<Label Padding="0" FontSize="10">Esc</Label>
<Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">Cancel</Label>
<Canvas>
<!-- Your Canvas content here -->
</Canvas>
</Grid>
</Button>
Repeating my solution from the comments, since (a) you really don't want a Canvas and (b) it sounds like this solved your problems, so I'll make it an answer where it will be more visible to others.
Canvas is meant for fixed-pixel-size layouts, which is probably the least common case. You should replace your Canvas with a Grid as shown below, so that both Labels are laid out dynamically (and independently) within the available space:
<Grid>
<Label Padding="0" FontSize="10">Esc</Label>
<Label VerticalAlignment="Center" HorizontalAlignment="Center">Cancel</Label>
</Grid>

Filling In GroupBox

I have a groupbox that contains nested stack panels that aren't filling in the groupbox entirely. I would like to have all the stackpanels evenly spaced out filling in the entire groupbox. I have attempted changing the VerticalContentAlignment to Stretch for the groupbox, but that does not work.
<GroupBox>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Test1" />
<Label Content="Test2"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="Test3" />
<Label Content="Test4"/>
</StackPanel>
</StackPanel>
</GroupBox
StackPanels by default only use as much space as is required to display whatever they contain. If you need different behavior you either need to roll your own version of a stackpanel or use another container. Both Grids/Dockpanels work fine as substitutes.

Resources