第十七章:掌握网格(五)

单元格分隔和边框
Grid没有任何内置的单元格分隔符或边框。 但是如果你想要一些,你可以自己添加它们。 GridCellDividers程序在其资源字典中定义名为dividerThickness的GridLength值。 这用于网格中每个其他行和列的高度和宽度。 这里的想法是这些行和列用于分隔符,而其他行和列用于常规内容:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridCellDividers.GridCellDividersPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0"
                    Android="0"
                    WinPhone="0" />
    </ContentPage.Padding>
    <Grid>
        <Grid.Resources>
            <ResourceDictionary>
                <GridLength x:Key="dividerThickness">2</GridLength>
 
                <Style TargetType="BoxView">
                    <Setter Property="Color" Value="Accent" />
                </Style>
                <Style TargetType="Label">
                    <Setter Property="HorizontalOptions" Value="Center" />
                    <Setter Property="VerticalOptions" Value="Center" />
                </Style>
            </ResourceDictionary>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="{StaticResource dividerThickness}" />
            <RowDefinition Height="*" />
            <RowDefinition Height="{StaticResource dividerThickness}" />
            <RowDefinition Height="*" />
            <RowDefinition Height="{StaticResource dividerThickness}" />
            <RowDefinition Height="*" />
            <RowDefinition Height="{StaticResource dividerThickness}" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{StaticResource dividerThickness}" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="{StaticResource dividerThickness}" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="{StaticResource dividerThickness}" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="{StaticResource dividerThickness}" />
        </Grid.ColumnDefinitions>
        <BoxView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="7" />
        <BoxView Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="7" />
        <BoxView Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="7" />
        <BoxView Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="7" />
        <BoxView Grid.Row="0" Grid.Column="0" Grid.RowSpan="7" />
        <BoxView Grid.Row="0" Grid.Column="2" Grid.RowSpan="7" />
        <BoxView Grid.Row="0" Grid.Column="4" Grid.RowSpan="7" />
        <BoxView Grid.Row="0" Grid.Column="6" Grid.RowSpan="7" />
        <Label Text="Grid"
               Grid.Row="1" Grid.Column="1" />
        <Label Text="Cell"
               Grid.Row="3" Grid.Column="3" />
        <Label Text="Dividers"
               Grid.Row="5" Grid.Column="5" />
    </Grid>
</ContentPage> 

分隔符的每一行和每列都被BoxView占据,其中的Obcent颜色来自隐式样式。 对于水平分隔符,高度由RowDefinition设置,宽度由Grid.ColumnSpan附加的可绑定属性控制; 类似的方法适用于垂直分隔线。
Grid还包含三个Label元素,只是为了演示常规内容如何适应这些分隔符:
第十七章:掌握网格(五)
没有必要将整行和列分配给这些分隔符。 请记住,可视对象可以共享单元格,因此可以将BoxView(或两个或三个或四个)添加到单元格并设置水平和垂直选项,使其拥抱单元格的墙壁并类似于边框。
这是一个名为GridCellBorders的类似程序,它在与GridCellDividers相同的三个单元格中显示内容,但这三个单元格也用边框装饰。
Resources字典包含不少于七种针对BoxView的样式! 基本样式设置颜色,另外两个样式设置水平和垂直边框的HeightRequest和WidthRequest,然后另外四个样式将VerticalOptions设置为Start和End为顶部和底部边框,HorizontalOptions设置为Start和End为左边和 正确的边界。 边框Thickness字典条目是double,因为它用于设置BoxView元素的WidthRequest和HeightRequest属性:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridCellBorders.GridCellBordersPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="10, 20, 10, 10"
                    Android="10"
                    WinPhone="10" />
    </ContentPage.Padding>
    <Grid>
        <Grid.Resources>
            <ResourceDictionary>
                <x:Double x:Key="borderThickness">1</x:Double>
                <Style x:Key="baseBorderStyle" TargetType="BoxView">
                    <Setter Property="Color" Value="Accent" />
                </Style>
                <Style x:Key="horzBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource baseBorderStyle}">
                    <Setter Property="HeightRequest" Value="{StaticResource borderThickness}" />
                </Style>
                <Style x:Key="topBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource horzBorderStyle}">
                    <Setter Property="VerticalOptions" Value="Start" />
                </Style>
                <Style x:Key="bottomBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource horzBorderStyle}">
                    <Setter Property="VerticalOptions" Value="End" />
                </Style>
                <Style x:Key="vertBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource baseBorderStyle}">
                    <Setter Property="WidthRequest" Value="{StaticResource borderThickness}" />
                </Style>
                <Style x:Key="leftBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource vertBorderStyle}">
                    <Setter Property="HorizontalOptions" Value="Start" />
                </Style>
                <Style x:Key="rightBorderStyle" TargetType="BoxView"
                       BasedOn="{StaticResource vertBorderStyle}">
                    <Setter Property="HorizontalOptions" Value="End" />
                </Style>
                <Style TargetType="Label">
                    <Setter Property="HorizontalOptions" Value="Center" />
                    <Setter Property="VerticalOptions" Value="Center" />
                </Style>
            </ResourceDictionary>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Text="Grid"
               Grid.Row="0" Grid.Column="0" />
        <BoxView Style="{StaticResource topBorderStyle}"
                 Grid.Row="0" Grid.Column="0" />
        <BoxView Style="{StaticResource bottomBorderStyle}"
                 Grid.Row="0" Grid.Column="0" />
        <BoxView Style="{StaticResource leftBorderStyle}"
                 Grid.Row="0" Grid.Column="0" />
        <BoxView Style="{StaticResource rightBorderStyle}"
                 Grid.Row="0" Grid.Column="0" />
        <Grid Grid.Row="1" Grid.Column="1">
            <Label Text="Cell" />
            <BoxView Style="{StaticResource topBorderStyle}" />
            <BoxView Style="{StaticResource bottomBorderStyle}" />
            <BoxView Style="{StaticResource leftBorderStyle}" />
            <BoxView Style="{StaticResource rightBorderStyle}" />
        </Grid>
        <Grid Grid.Row="2" Grid.Column="2">
            <Label Text="Borders" />
            <BoxView Style="{StaticResource topBorderStyle}" />
            <BoxView Style="{StaticResource bottomBorderStyle}" />
            <BoxView Style="{StaticResource leftBorderStyle}" />
            <BoxView Style="{StaticResource rightBorderStyle}" />
        </Grid>
    </Grid>
</ContentPage> 

在左上角的单元格中,Label和四个BoxView元素各自将其Grid.Row和Grid.Column属性设置为0.但是,对于中间网格和右下角网格,采用了一种相当简单的方法 :具有单个单元格的另一个网格占据单元格,并且该单单元格网格包含Label和四个BoxView元素。 只需在单格网格上设置Grid.Row和Grid.Column即可实现简单性:

<Grid Grid.Row="1" Grid.Column="1">
    <Label Text="Cell" />
    <BoxView Style="{StaticResource topBorderStyle}" />
    <BoxView Style="{StaticResource bottomBorderStyle}" />
    <BoxView Style="{StaticResource leftBorderStyle}" />
    <BoxView Style="{StaticResource rightBorderStyle}" />
</Grid>

将Grid嵌套在另一个Grid中时,使用Grid.Row和Grid.Column属性可能会造成混淆。 此单元格网格占据其父级的第二行和第二列,即占据整个页面的网格。
另外,请记住,当Grid自行铺设时,它只会查看其子项的Grid.Row和Grid.Column设置,而不会查看其可视树中的孙子或其他后代。
这是结果:
第十七章:掌握网格(五)
边界的角落不符合可能有点令人不安,但这是由于网格的默认行和列间距。 将RowSpacing和ColumnSpacing属性设置为0,并且角将会遇到,尽管这些线仍然看起来有些不连续,因为边框位于不同的单元格中。 如果这是不可接受的,请使用GridCellDividers中显示的技术。
如果您希望在GridCellDividers中显示所有带有分隔符的行和列,则另一种技术是设置Grid的BackgroundColor属性,并使用RowSpacing和ColumnSpacing属性让该颜色透过单元格之间的空间。 但是所有细胞必须包含具有不透明背景的内容,以使这种技术具有视觉上的说服力。