常见的Grid 布局代码如下:
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--(600-30-350)*(80/(80+20))=176-->
<ColumnDefinition Width="80*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="Auto" Width="350" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="80*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="20*" Grid.Column="2"/>
<TextBlock Background="Bisque" Text="30" Grid.Column="3"/>
</Grid>
ColumnDefinition 的属性Width值有三种类型,
Msdn 解释如下:
Auto | The size is determined by the size properties of the content object. | |
Pixel | The value is expressed as a pixel. | |
Star | The value is expressed as a weighted proportion of available space. |
Auto:根据子控件的要求,给予需要的控件
Pixel:固定值
Star:按照加权比例分配。
如果三者混合使用,该如何分配呢,看下图
分析源代码
第一行:
<!--If you set ColumnDefinition Width is pixel value,this column's width will be a fixed value,maybe there is free space-->
<Grid Height="30" VerticalAlignment="Top" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="50" Grid.Column="0"/>
<TextBlock Background="RosyBrown" Text="50" Grid.Column="1"/>
<TextBlock Background="Bisque" Text="50" Grid.Column="2"/>
</Grid>
每一列都是固定数值,剩余空间留空。
第二行:
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="True">
<Grid.ColumnDefinitions>
<!--600*(40/(40+40+20))=240-->
<ColumnDefinition Width="40*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="40*"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="40*" TextAlignment="Center" Grid.Column="0"/>
<TextBlock Background="RosyBrown" Text="20*" Grid.Column="1"/>
<TextBlock Background="Bisque" Text="40*" Grid.Column="2"/>
</Grid>
每一列都是加权数值,按照比例分配,
例如,Grid总宽度为600,第一列宽度值为40* ,实际数值为 600*(40/(40+40+20))=240 。
第三行:
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<!--(600-100)*(40/(40+60))=200-->
<ColumnDefinition Width="40*"/>
<ColumnDefinition Width="60*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="40*" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="60*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="100" Grid.Column="2"/>
</Grid>
这一列既有固定数字,也有加权比例,该如何计算呢?
以第一列为例,总宽度依然为600
先减去固定的数值100,剩下的部分 由两个加权比例列(40*/60*)瓜分,如下:
600-100)*(40/(40+60))=200
第四行:
<!--If the ColumnDefinition width is star ,and others is not, the start mean "1*",calculate as above -->
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<!--(600-30)*(1/(1+30))=18.3-->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="*" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="30*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="30" Grid.Column="2"/>
</Grid>
注意,第一列宽度为* ,第二列为30* ,这个该如何处理呢?当有两个加权分配时,其中的* 实际含义为1*,所以第一列宽度为
(600-30)*(1/(1+30))=18.3
第五行:
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--(600-30-350)*(80/(80+20))=176-->
<ColumnDefinition Width="80*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="Auto" Width="350" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="80*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="20*" Grid.Column="2"/>
<TextBlock Background="Bisque" Text="30" Grid.Column="3"/>
</Grid>
最复杂的就是这一列,各种东东都混合进来了,一个一个来吧。
第一列,Auto,看这一列的控件,锁定了宽度350,那么第一列就固定了350
第二、三列为加权比例,先放放
第四列固定宽度,不用考虑了。
那么第二列宽度为
(600-30-350)*(80/(80+20))=176
第六行
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--(600-30-380)=190-->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="Auto" Width="380" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="30" Grid.Column="2"/>
</Grid>
三种值类型同时出现,加权列的优先级最低,固定列的优先级最高。
第二列的计算方式为
(600-30-380)=190
另外,用cs代码定义GridLength 这样写:
GridLength fixedLength = new GridLength(20);
GridLength starLength = new GridLength(20, GridUnitType.Star);
GridLength autoLength = GridLength.Auto;
上例中XAML 完整代码如下
<StackPanel Width="600">
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextAlignment" Value="Center" />
</Style>
</StackPanel.Resources>
<!--If you set ColumnDefinition Width is pixel value,this column's width will be a fixed value,maybe there is free space-->
<Grid Height="30" VerticalAlignment="Top" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="50" Grid.Column="0"/>
<TextBlock Background="RosyBrown" Text="50" Grid.Column="1"/>
<TextBlock Background="Bisque" Text="50" Grid.Column="2"/>
</Grid>
<!--If the ColumnDefinition width is all star value,this column's width will be the whole value multiplication it's rate -->
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="True">
<Grid.ColumnDefinitions>
<!--600*(40/(40+40+20))=240-->
<ColumnDefinition Width="40*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="40*"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="40*" TextAlignment="Center" Grid.Column="0"/>
<TextBlock Background="RosyBrown" Text="20*" Grid.Column="1"/>
<TextBlock Background="Bisque" Text="40*" Grid.Column="2"/>
</Grid>
<TextBlock HorizontalAlignment="Left" Text="600*(40/(40+40+20))=240" Width="240" Height="30" Margin="0,0,0,0" Background="YellowGreen" />
<!--If the ColumnDefinition width is star value,and others is not, the whole value subtrace fixed value that which column's width is fixed value
then multiplication it's rate -->
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<!--(600-100)*(40/(40+60))=200-->
<ColumnDefinition Width="40*"/>
<ColumnDefinition Width="60*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="40*" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="60*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="100" Grid.Column="2"/>
</Grid>
<TextBlock HorizontalAlignment="Left" Width="200" Text="(600-100)*(40/(40+60))=200" Height="30" Margin="0,0,0,0" Background="YellowGreen" />
<!--If the ColumnDefinition width is star ,and others is not, the start mean "1*",calculate as above -->
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<!--(600-30)*(1/(1+30))=18.3-->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="*" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="30*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="30" Grid.Column="2"/>
</Grid>
<TextBlock HorizontalAlignment="Left" Width="18.3" Height="30" Margin="0,0,0,0" Background="YellowGreen"
Text="18.3" ToolTip="(600-30)*(1/(30+1))=18.3" />
<!--If the ColumnDefinition width is Auto ,it's width will be determined by content width,the content object has highest priority.if it want,it can use all space of parent -->
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--(600-30-350)*(80/(80+20))=176-->
<ColumnDefinition Width="80*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="Auto" Width="350" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="80*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="20*" Grid.Column="2"/>
<TextBlock Background="Bisque" Text="30" Grid.Column="3"/>
</Grid>
<TextBlock HorizontalAlignment="Left" Text="(600-30-350)*(80/(80+20))=176" Width="176" Height="30" Margin="350,0,0,0" Background="YellowGreen" />
<Grid Height="30" Margin="0,20,0,0" VerticalAlignment="Top" ShowGridLines="False" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--(600-30-380)=190-->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Text="Auto" Width="380" Grid.Column="0" />
<TextBlock Background="RosyBrown" Text="*" Grid.Column="1" />
<TextBlock Background="Bisque" Text="30" Grid.Column="2"/>
</Grid>
<TextBlock Background="YellowGreen" HorizontalAlignment="Left" Margin="380,0,0,0" Height="30" Text="(600-30-380)=190" Width="190" />
</StackPanel>