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>
作者: xiaokang088 发表于 2011-04-29 10:04 原文链接