Grid之 Gridlength 解析
常见的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>