Autosizing a grid column to take up remaining space in parent - wpf

In WPF, I am having a heck of a time trying to get a grid to size properly.
I have the following layout for my grid:
<ItemsControl HorizontalContentAlignment="Stretch">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" />
<Label Grid.Column="1"/>
<TextBox Grid.Column="2"/>
<Button Grid.Column="3"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The problem is that Width="Auto" seems to be sizing that column to the width of the content, and not filling out the extra space in the parent container. This leaves the rest of the columns all unaligned, and ugly blank space at the end of each row.
I'm probably missing something simple, but I can't seem to find a method to fit the column appropriately.
Or is there a better control for the job?

* means fill or share. If you had two with * then they would share the width evenly.
<ColumnDefinition Width="*"/>

Seems I found a solution after a bit more tinkering around.
The problem was: <ColumnDefinition Width="Auto"/>
This was causing the column to fit to the content. I changed it to: <ColumnDefinition />
This causes the column to fit to the empty space left in the parent container, regardless of content size.

Related

DataTemplate of Grid inside ListView is not resizing

I have a ListView that lays on top of UI graphics in my UserControl that I want to show and size using a Grid that matches the parent grid. I'm trying to template the way each item shown and sized using the ListView.ItemTemplate. The issue I'm having is that the DataTemplate is not sizing to the main Grid of the UI, and I'm not sure why.
This is what I've done, I think it a fairly simple and straight forward datatemplate:
<ListView ItemsSource="{Binding Path=StatusFilter}" Grid.Row="2" Grid.ColumnSpan="12">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="92"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="85"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
<ColumnDefinition Width="90*"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Path=ECNNumber}" Grid.Column="0"/>
<Label Content="{Binding Path=DateECNDue}" Grid.Column="1"/>
<Label Content="{Binding Path=Model.Model}" Grid.Column="2"/>
<--More stuff for each column-->
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When this is displayed the grid is completely bypassed and each element is shown like a horizontally aligned stackpanel. To test that my DataTemplate wasn't faulty I threw it into an ItemsControl and it worked perfectly. It resized with the parent grid without any issues.
Why isn't this working for the ListView, and how do I get it to work? I need the selection and scrollview capability of the ListView otherwise I'd be using the ItemsControl.
I read something about Grid.SharedSizeScope but that doesn't work with dynamic sizing of grid, and that's all I could really find on this issue.

Auto Sizing between grid columns

I have two controls and a GridSplitter .
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<UserControlOne Grid.Colum="0" Visibility="{Binding MyProperty1}"/>
<GridSplitter Visibility="{Binding MyProperty1}" m:Splitterbehaviour.Apply= true/>
<UserControlTwo Grid.Colum="1" />
</Grid>
I am trying to show/hide the UserControlOne with the MyProperty1 which is working fine but when it is hidden i want the UsercontrolTwo to take whole page space. I could easily achieve this by using a stack or dock panel. But if i use the stackpanel or dockpanel my GridSplitter wont work.(I have a behaviour set to GridSplitter which will identify the first column and it will help to resize the first and second column)
I don't see how that splitter is working
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<UserControlOne Grid.Colum="0" Visibility="{Binding MyProperty1}"/>
<UserControlTwo Grid.Colum="1"/>
</Grid>

How to layout controls and make it resizable

I would like to place the controls as listed below in WPF. Please given an example to do the same.
<Grid x:Name="ContentRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" .../>
<TextBox Grid.Column="1" .../>
<Button Grid.Column="2" .../>
<Button Grid.Column="3" .../>
</Grid>
Assuming that ContentRoot is placed directly in your Window, it'll inherit it's Width and Height from the Window. Then it'll assign 200px to the 0th column, and 100px each to the 2nd and 3rd columns. And any leftover space will be assigned to the 1st column.
Of course, you can change 200, 100, and 100 to whatever you want.
If needed, add MinWidth="<value>" (replace <value> with a number) in the 1st ColumnDefnition to specify a minimum width that column must have.

WPF - Resizing Children to Fill a Parent

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.

Text wrapping expands the column to fit the text

I've got a grid defined simply:
<Grid Margin="0,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="48"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
Then I'm trying to bind some content like this:
<TextBlock TextWrapping="Wrap" Grid.Column="3" Text="{Binding Text}">
Set up like this, the text won't wrap. It simply expands the column to fit the text. If I set the Width to a fixed amount on the last column, wrapping works as expected. The problem there is that if the user widens the window, the column stays at a fixed size. How can I get the column to size dynamically with the width of the grid, but still wrap the text within it?
A width of "*" will split any remaining space evenly between the columns using "*". If you have a single column with Width="*", that column will get all remaining space. If you have 2 columns with Width="*", each will get 1/2 of the remaining space.
Here's a good article on grid sizing that includes star sizing.
There's one frustrating case I discovered that can break even with Width="*" and thats when you have IsSharedSizeScope= true.
<Border BorderBrush="Red" BorderThickness="1">
<StackPanel Grid.IsSharedSizeScope="True">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="G1"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="G2" />
<ColumnDefinition Width="*" SharedSizeGroup="G3" />
</Grid.ColumnDefinitions>
<TextBlock Text="Col0" Grid.Column="0" Margin="0,0,5,0"/>
<TextBlock Text="Col1" Grid.Column="1" Margin="0,0,5,0"/>
<TextBlock Text="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" TextWrapping="Wrap" Grid.Column="2"/>
</Grid>
</StackPanel>
</Border>
This won't wrap, but if you change Grid.IsSharedScopeSize to false then it does.
Haven't found a solution yet, but this can be another reason it won't work.
Try this:
<Grid Margin="0,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="48"></ColumnDefinition>
<ColumnDefinition Name="ParentColumn" Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Grid.Column="3" Text="{Binding Text}"
MaxWidth="{Binding ActualWidth, ElementName=ParentColumn}">
Set its width to "*"
You should use Auto only when you want to column/row to size depending on content in said column/row. If you want to "asign rest of space" use "*".
In your case, TextBlock needs to know how much space it has before acutal measure, so it can tell where to wrap the text.

Resources