What does the WPF star do (Width="100*") - wpf

What does exactly the star in size terms in WPF mean?

In a WPF Grid, Width="*" or Height="*" means proportional sizing.
For example: to give 30% to column 1 and 70% to column 2 -
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />
And likewise for rows -
<RowDefinition Height="3*" />
<RowDefinition Height="7*" />
The numbers do not have to be integers.
If the Width for RowDefinition (Height for ColumnDefinition) is omitted, 1* is implied.
In this example, column 1 is 1.5 times wider than column 2 -
<ColumnDefinition Width="1.5*" />
<ColumnDefinition />
You can mix auto-fit and fixed widths with * (proportional) widths; in that case the * columns are apportioned to the remainder after the auto-fit and fixed widths have been calculated -
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- Auto-fit to content, 'Hi' -->
<ColumnDefinition Width="50.5" /> <!-- Fixed width: 50.5 device units) -->
<ColumnDefinition Width="69*" /> <!-- Take 69% of remainder -->
<ColumnDefinition Width="31*"/> <!-- Take 31% of remainder -->
</Grid.ColumnDefinitions>
<TextBlock Text="Hi" Grid.Column="0" />

If you have 2 columns like this:
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="*"/>
it means that the first column is 10x wider than the second. It's like saying "10 parts column 1, and 1 part column 2."
The cool thing about this is that your columns will resize proportionally. Other options are:
//Take up as much space as the contents of the column need
<ColumnDefinition Width="Auto"/>
//Fixed width: 100 pixels
<ColumnDefinition Width="100"/>
Hope that helps!

we take following example.....
A grid has 3 columns each containing one button of width 100.
XAML Code is...
<Grid x:Name="LayoutRoot" Width="600">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="button1" VerticalAlignment="Top" Width="100" />
<Button Content="Button1" Height="23" HorizontalAlignment="Left" Margin="0,10,0,0" Name="button2" VerticalAlignment="Top" Width="100" Grid.Column="1" />
<Button Content="Button2" Height="23" HorizontalAlignment="Left" Margin="0,10,0,0" Name="button3" VerticalAlignment="Top" Width="100" Grid.Column="2" />
</Grid>
But actually its size is....
<Grid.ColumnDefinitions>
<ColumnDefinition Width="375" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="125" />
</Grid.ColumnDefinitions>
Conclusions:
Total size of grid is 600
Auto : Column is resizes based on it's contents. (2nd column has button of width 100)
* : 1st column width is 3x of 3rd column.

In addition, you can leave out the "*" if that's the element of unit size. So using Pwninstein's code example, it would just be:
<ColumnDefinition Width="10*/>
<ColumnDefinition/>

Related

Specify a width for a grid column

I'm using a grid to define a form with this column template :
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
But I need for a specific row to use another column template :
<Label Grid.Column="0" Grid.Row="4">N°</Label>
<TextBox Grid.Column="1" Grid.Row="4" Name="idNum"></TextBox>
<ComboBox Grid.Column="2" Grid.Row="4" Name="idVoie" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedValue="."></ComboBox>
<TextBox Grid.Column="3" Grid.Row="4" Name="idAdr"></TextBox>
with the first three field being 1* and the last field using the free space.
Of course, I can't specify the width directly in the field with percent.
Thanks for your help
You can use a nested grid for that particular row, which spans all four columns of your outer grid:
<Grid Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0">N°</Label>
<TextBox Grid.Column="1" Grid.Row="0" Name="idNum"></TextBox>
<ComboBox Grid.Column="2" Grid.Row="0" Name="idVoie" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedValue="."></ComboBox>
<TextBox Grid.Column="3" Grid.Row="0" Name="idAdr"></TextBox>
</Grid>
Note I'm assuming when you refer to 1* you mean as relative to the grid you already have, i.e. the same size as the first and third columns. Therefore you have a total of 8* across the row, and I've calculated the relative widths for your row to be 1*, 1*, 1*, 5*.

UserControl cropped when used in MainWindow

Hello Stackoverflowers !
I'm creating a list with a searchbar in XAML, and when i tried to use my new UserControl in MainWindow.xaml, the Button in the UserControl is cropped in the designer instead of being resized to fit, why is that ?
Here is the MainWindow.xaml body :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="8*" />
</Grid.ColumnDefinitions>
<controls:SearchBox Grid.Column="0"/>
</Grid>
And here is the body of the custom control :
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="8*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox
Grid.Row="0"
VerticalAlignment="Center"
Text="Search"
TextBlock.FontStyle="Italic"
TextBlock.TextAlignment="Left"
/>
<!-- Content="{StaticResource FilterLogo}" -->
<Button
Grid.Column="1"
Content="Filter"
VerticalAlignment="Center"
HorizontalAlignment="Stretch">
</Button>
<ListBox
Grid.Row="1"
Grid.ColumnSpan="2"
ItemsSource="{Binding DataContext}"
SelectedItem="{Binding DataContext}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
I don't really know why my control is cropped to be honest. Any lead please ?
Short answer: it doesn't fit.
You have two columns in your main window. Since you have not specified which column to place the UserControl, it defaults to the first column. But your Width definitions force that column to be one fourth the size of the second column.
Your SearchBox simply doesn't fit in the space you have allotted to it.
If you remove the star (*) from this line:
<ColumnDefinition Width="8*" />
...it will fit without being cropped. (Alternatively, you could place the user control in the second column, or expand the main window, or shrink the width of your UserControl.)
When using stars in the column and row definitions, use them like percentages. Like this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*" /> <!-- 10% -->
<ColumnDefinition Width=".9*" /> <!-- 90% -->
</Grid.ColumnDefinitions>
This is what the XAML reader interpreted from your usage:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" /> <!-- 800% -->
<ColumnDefinition Width="*" /> <!-- 100% -->
</Grid.ColumnDefinitions>
This will have undesired results.

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.

Why does the WPF Grid not share space equally when the middle column has a MinWidth?

In this example the first column gets 100 and the next 2 columns get 50 each, which is the expected behaviour.
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="100" />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="Red" Grid.Column="0" />
<Border Background="Yellow" Grid.Column="1" />
<Border Background="Blue" Grid.Column="2" />
</Grid>
If I move the MinWidth to the middle column ...
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition MinWidth="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="Red" Grid.Column="0" />
<Border Background="Yellow" Grid.Column="1" />
<Border Background="Blue" Grid.Column="2" />
</Grid>
... then the first column gets 33.3 and the last column 66.6 which seems weird. Not sure why this should change the grid's behaviour. I would expect columns 0 and 2 to get 50 each.
Update: I understand why this happens, but was wondering if anyone thinks it is a bug (especially since the behaviour in Silverlight is different)
This issue only arises when you have a center column, which implies you have an odd number of columns defined for your grid. I'm not sure why this is happening nor do I think it's intentional behavior. But, another workaround is to always ensure you have an even number of columns defined even if you are only utilizing an odd number of them (hiding the extra column using MaxWidth=0).
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" MinWidth="100"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" MaxWidth="0"/> <!--Workaround-->
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="Red"/>
<Border Grid.Column="1" Background="Yellow"/>
<Border Grid.Column="2" Background="Blue"/>
</Grid>
Disadvantage here is you have an empty column in your grid. The advantage is you get the expected space distribution behavior.
Just an update.. I have tried the XAML snippet with a combination of .NET 3.5/4.0 Silverlight 3/4 and still could not get equal width for the second example...
This XAML was the only way around that issue:
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition MinWidth="100" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Border Background="Red" Grid.Column="0" />
<Border Background="Yellow" Grid.Column="1" />
<Border Background="Blue" Grid.Column="2" />
</Grid>
Any update on your side guys?
not sure exactly what the issue is, but these two grids behave the way you want them to. I like the second more than the first since it explicitly specifies that the first and third column should take up leftover space equally.
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition MinWidth="100" Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="Red" Grid.Column="0" />
<Border Background="Yellow" Grid.Column="1" />
<Border Background="Blue" Grid.Column="2" />
</Grid>
<Grid Width="200" Height="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition MinWidth="100" Width="Auto" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Border Background="Red" Grid.Column="0" />
<Border Background="Yellow" Grid.Column="1" />
<Border Background="Blue" Grid.Column="2" />
</Grid>
If you want equal width, you cannot use Auto. You must explicitly set the width of every column to the desired proportion, for 3 columns you want ".3*" for each.
MinWidth takes precedence if the calculated Width becomes smaller than MinWidth.

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