WPF - Resizing Children to Fill a Parent - wpf

In WPF, I simply want to have a 'container' which has 3 textblocks. I would like these 3 textblocks to be sized so they each take up 1/3 of the parent's width. I noticed that the stackpanel sizes the last child automatically, but is there a way to size each child automatically?

Use a Grid or a UniformGrid
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="1" Grid.Column="0"/>
<TextBlock Text="2" Grid.Column="1"/>
<TextBlock Text="3" Grid.Column="2"/>
</Grid>
The grid is very common and in every WPF-App used a lot. However also the UniformGrid is very handy but not so well known.

Related

Width of Textbox, which placed in grid column, extends when inserting long text

When I put a Textbox in a grid column like below
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="115"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="hello"/>
<TextBox Grid.Column="1" />
<Button Grid.Column="2" Content="push me"/>
</Grid>
</StackPanel>
I get proper result, i.e. textbox width is get from parent grid
But when I type a long text, the textbox starts exceeding its column and it stops extending after several extra letters
To .Net 4.6.2, I get same result but changing to .Net 4.7.2 the problem is solved i.e. the textbox width is not changing.
My software is compiled .Net 4.0, is there a solution to solve this for lower .net than 4.7.2?
Tried Pavel's first idea: removing stackpanel and adding another grid row in, still not working in .net 4.6.2
Tried Pavel's second idea: making the width of first column "Auto" instead of "1*". This works, the textbox doesn't extend (.net 4.6.2), however I really wanted the first and second column be responsive to resize.
You can solve this be removing the StackPanel and adding RowDefinition to Grid. You can also set TextWrapping="Wrap" for TextBox for wrapping a long text
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="hello" MinWidth="115"/>
<TextBox Grid.Column="1" TextWrapping="Wrap"/>
<Button Grid.Column="2" Content="push me"/>
</Grid>
StackPanel Y dimension is constrained to content, it will be automatically expanded to its content, more details can be found at panels overview
To me this is a bug that Textbox text size can change its parent width (grid width). This is happening in VS2019 .Net 4->4.6.2 but not in and after .Net 4.7.2.
For anybody faces this problem, I found below workaround by defining an invisible grid which contains textblocks. I get the widths of columns and give them to controls placed in a StackPanel.
<some container>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="115"/>
<ColumnDefinition Width="3*" />
<ColumnDefinition MinWidth="90"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
</Grid.RowDefinitions>
<TextBlock x:Name="C0" Grid.Column="0" />
<TextBlock x:Name="C1" Grid.Column="1" Margin="5"/>
<TextBlock x:Name="C2" Grid.Column="2" />
</Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Width="{Binding ElementName=C0, Path=ActualWidth }" Text="hello" />
<TextBox Width="{Binding ElementName=C1, Path=ActualWidth }" Margin="5" />
<Button Width="{Binding ElementName=C2, Path=ActualWidth }" Content="push me"/>
</StackPanel>
</some container>
The margin should be the same for column in grid and control in StackPanel (see second column).

ItemsControl/ListBox items exceed available width

I want text in column 3 wrap and have no horizontal scrollbar. Why doesn't this work?
<ItemsControl x:Name="listMessages" ItemsSource="{Binding Messages}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Column1"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="Column2"/>
<ColumnDefinition Width="*" SharedSizeGroup="Column3"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="Column4"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Text1" />
<TextBlock Grid.Column="1" Text="Text2" />
<TextBlock Grid.Column="2" Text="Very long text that should wrap to the next line, but it doesn't work" TextWrapping="Wrap"/>
<TextBlock Grid.Column="3" Text="Text4" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Items take more width than is available to ItemsControl. Same problem is with ListBox.
I tried to add ScrollViewer.HorizontalScrollbarVisibility=Disabled both on ItemsControl and Grid, but this doesn't help.
The text will be wrapped if you don't set the SharedSizeGroup property:
<ColumnDefinition Width="*"/>
Text wrapping and shared size groups don't go well together. You may want to specify a fixed MaxWidth for the ColumnDefinition or the TextBlock.

WPF Grid - Shrink one column on window resize to keep all content on screen

I have a 5 column grid in WPF which displays some dynamic data. Columns 1,2 and 4 are fixed width as they are effectively labels, but 2 and 5 can be of different lengths.
Column 3 should wrap to make sure all content is shown but can expand to a maximum width of 390. But column 5 should remain on a single line. When I resize the window, everything must remain on screen without a horizontal scrollbar. The middle (3rd) column should shrink down to keep the 4th and 5th columns on screen.
Current behaviour: Column 3 will wrap when the contents expand beyond 390, but resizing the window will not cause this column to resize, but will cause column 5 then 4 disappear off screen.
Here's the code so far:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid x:Name="ListItemControl"
Grid.Column="0"
MinHeight="50"
Width="auto"
VerticalAlignment="Top">
<Border Background="LightBlue"
Margin="1,0,1,1" />
<Grid VerticalAlignment="Center"
Margin="20,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="130" />
<ColumnDefinition Width="*"
SharedSizeGroup="col2" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="auto"
SharedSizeGroup="col4" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="50" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
Margin="0,10,0,10"
Text="Due" />
<TextBlock Grid.Column="1"
Grid.Row="0"
Margin="0,10,10,10"
Text="Some Date" />
<TextBlock Grid.Column="2"
Grid.Row="0"
Margin="0,10,30,10"
Text="There is some potentially long text here. This is a placeholder and should wrap."
TextWrapping="Wrap"
MaxWidth="390" />
<TextBlock Grid.Column="3"
Grid.Row="0"
Margin="0,10,10,10"
Text="Who's responsible" />
<TextBlock Grid.Column="4"
Grid.Row="0"
Margin="0,10,10,10"
Text="Name - could be a very long name" />
</Grid>
</Grid>
</Grid>
Any help greatly appreciated!
Your ListItemControl Grid is inside another Grid with a single column, dont know the reason. Remove that parent Grid and you are done.

I'm confused with Grid layout in ListBoxItem of WPF

I'm newer in wpf,recently i have a requirement need to create an listbox and when i practice in DataTemplate ,the issue comed.my layout code like below
<ListBox HorizontalAlignment="Stretch" HorizontalContentAlignment="Left">
<ListBoxItem HorizontalAlignment="Stretch">
<Grid ShowGridLines="True" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.ColumnSpan="2"
Width="200" Height="40" Fill="Gray"/>
</Grid>
</ListBoxItem>
</ListBox>
the begining,i set the width 100 on the first column,because the Rectange's width become to 200,so the first column width become more greater than 100,what happend when the grid to measue the child element?i am confused about it ,because i put the code in an commen state it run normally.any one tell me ,thanks

Silverlight - Auto-resize textbox to fill up empty space

Ok this is what I wish to do.
I have a resizeable window which has 3 controls in same row in flowing order: textBlock, textBox and button.
textBlock and button have dynamic texts. So theirs size depends upon text inside.
Now what I wish to do is that textBox in the middle is always filling up all empty space between textBlock and button.
How do I do that?
I tried with the following code but it doesn't work because of fixed width in 1. and 3. column.
<Grid Margin="0,0,5,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" HorizontalAlignment="Left" Text="Text1"/>
<TextBox Grid.Column="1"/>
<Button Grid.Column="2" Content="Button1" HorizontalAlignment="Center"/>
</Grid>
You can use Auto for the two outer column widths instead of specifying the width
<Grid Margin="0,0,5,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Text1" />
<TextBox Grid.Column="1"/>
<Button Grid.Column="2" Content="Button1" />
</Grid>
You probably don't need the HorizontalAlignment in the columns either

Resources