WPF_17_DataGrid

ListView

ListView专门针对显示相同数据的不同视图而设计的,常用于显示每个数据项几部分信息的多列视图。ListView继承自ListBox类,并使用View属性进行扩展。

从技术角度看,View指向继承自ViewBase类的任意实例。ViewBase是一个将两个样式捆绑在一起的包,其中一个样式应用到ListView控件(通过DefaultStyleKey属性),而另一个应用到ListView控件中的项(通过ItemContainerDefaultStyleKey属性)。

事实上,为创建能够自定义的具有多列的列表,不需要使用具有View属性的ListView类。通过ListBox控件使用模板和样式也可获得相同的效果。但View属性是一个很有用的抽象概念,其优点有:

  • 可重用的视图
  • 多视图
  • 更好的组织
使用GridView创建列
<ListView Name="lstProducts">
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="Name" 
                    DisplayMemberBinding="{Binding Path=ModelName}"/>
                <GridViewColumn Header="Model"
                    DisplayMemberBinding="{Binding Path=ModelNumber}"/>
                <GridViewColumn Header="Price"
                    DisplayMemberBinding="{Binding Path=UnitCost, StringFormat={}{0:C}}"/>
            </GridView.Columns>
        <GridView>
    </ListView.View>
</ListView>

为了在单元格中显示数据,DisplayMemberBinding属性不是唯一的方式,通过设置 CellTemplate 属性也可以。

<GridViewColumn Header="Price" Width="100">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Description}" TextWrapping="Wrap"/>
            <!--<Image Source="{Binding Path=ProductImagePath, Converter={StaticResource ImagePathConverter}}>-->
        </DataTemplate>
    <GridViewColumn.CellTemplate>
</GridViewColumn>

因为要绑定到具体的字段,所以不同列没办法重用模板。
如果同时设置了 DisplayMember 和 CellTemplate 属性,会使用前者为单元格设置内容并忽略模板。

TreeView

TreeView控件在本质上是驻留 TreeViewItem 对象的特殊ItemsControl控件。每个TreeViewItem对象都是单独的ItemsControl 控件,可以包含更多的 TreeViewItem 对象。

从技术角度看,TreeViewItem类继承自HeaderedItemsControl类,该类又继承自ItemsControl类。WPF还提供了另外两个HeaderedItems类:MenuItem和ToolBar.

创建数据绑定的TreeView控件
public class Category : INotifyPropertyChanged
{
    private string categoryName;
    public string CategoryName
    {
        get { reutrn categoryName; }
        set {
            categoryName = value;
            OnPropertyChanged(new PropertyChangedEventArgs("CategoryName"));
        }
    }

    private ObservableCollection<Product> products;
    public ObservableCollection<Product> Products
    {
        get { reutrn products; }
        set {
            products = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Products"));
        }
    }
}

为了显示CategoryName属性,需要提供能处理绑定对象的 TreeView.ItemTemplate.

<TreeView>
    <TreeView.ItemTemplate>
        <!--HierarchicalDataTemplate能够封装第二个模板-->
        <!--两个模板分别用于两个层次,第二个模板使用从第一个模板中选择的项作为数据源-->
        <HierarchicalDataTemplate ItemsSource="{Bindign Path=Products}">
            <TextBlock Text="{Binding Path=CategoryName}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=ModelName}"/>
                </DataTemplate>
            <HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

上面的方式是同时设置了两层模板,但分解每个数据模板并通过数据类型(而不是位置)将之应用到数据对象的情况更加普遍。

<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:Category}" 
        ItemsSource="{Binding Path=Products}">
        <TextBlock Text="{Binding Path=ModelName}"/>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type local:Product}">
        <TextBlock Text="{Binding Path=ModelName}"/>
    </HierarchicalDataTemplate>
</Widnow.Resources>
<!--TreeView没有显示设置ItemTemplate,而是根据绑定对象的数据类型匹配-->
<TreeView />

DataGrid

DataGrid控件的基本显示属性如下:

属性名说明
RowBackground绘制每行背景的画刷
AlternatingRowBackground绘制交替行,默认奇数白色背景,偶数灰色背景
ColumnHeaderHight顶部的列标题行的高度
RowHeaderWidth行头的宽度
ColumnWidth每列默认宽度
RowHeight每行的高度
GridLinesVisibility是否显示网格线的 DataGridGridlines枚举值
VerticalGridLinesBrush绘制列之间网格线的画刷
HorizontalGridLinesBrush绘制行之间网格线的画刷
HeadersVisibility是否显示行头和列头
HorizontalScrollBarVisibility是否显示水平滚动条
VerticalScrollBarVisibility是否显示垂直滚动条
CanUserReorderColumns是否允许拖动列来改变显示顺序
CanUserResizeColumns是否允许调整列的宽度
AutoGenerateColumns是否自动根据公共属性生成列
自定义列

DataGrid控件支持集中类型的列,通过继承自DataGridColumn的不同类来表示:

  • DataGridTextColumn - 值被转换为文本,并在TextBlock中显示;当编辑行时,TextBlcok元素被替换为标准的文本框
  • DataGridCheckBoxColumn - 列显示复选框,为Boolean值自动使用这种类型。通常,复选框是只读的;当编辑行时,会变成普通的复选框
  • DataGridHyperlinkColumn - 列显示可单击的链接
  • DataGridComboBox - 编辑模式下会变成下拉的 ComboBox控件
  • DataGridTemplateColumn - 允许为显示列值定义数据模板
设置列的格式和样式

可使用与设置TextBlock元素格式相同的方式设置 DataGridTextureColumn 元素的格式,但并没有提供TextBlock的所有属性,这种情况可使用 ElementStyle 属性。ElementStyle属性用于创建应用于 DataGrid 单元格内部的元素的样式。

<DataGridTextColumn>
    <DataGridTextColumn.ElementStyle>
        <Style TargetType="TextBlock">
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

DataGrid提供了少部分用于设置网格其他部分格式的额外属性:

属性样式的使用范围
ColumnHeaderStyle位于网格顶部的列题头的 TextBlock
RowHeaderStyle行题头的 TextBlock
DragIndicatorStyle当用户正在将列题头拖动到新位置时用于列题头的 textBlock
RowStyle用于普通行(没设置ElementStyle属性)的 textBlock
ElementStyle用于创建应用于DataGrid单元格内部元素的样式
设置行的格式

对于设置行格式,LoadingRow事件是个强大的工具,允许开发者对当前行数据进行简单的范围检查、比较以及更复杂的操作。

当每一行出现在屏幕上时,会立即引发 LoadingRow 事件,这样不会格式化整个网格。为降低内存开销,在数据中滚动时DataGird控件为显示新数据而重用相同的DataGridRow对象(这也是为什么叫LoadingRow而不是CreatingRow的原因)。如果不慎,DataGrid控件能够将数据加载到已经格式化了的DataGridRow对象中。

// 为价格较高的项提供明亮的橙色背景
private void gridProducts_LoadingRow(object sender, DataGridRowEventArgs e)
{
    // 获取行数据对象
    Product product = (Product)e.Row.DataContext;

    // 条件
    if (product.UnitCost > 100)
    {
        e.Row.Background = highlightBrush;
    }
    else
    {
        e.Row.Background = normalBrush;
    }
}
显示行细节

行细节是一块可选的独立显示区域,在行的列值的下面显示:

  • 能够跨越DataGrid控件的整个宽度,并且不会切入到独立的列中,从而提供了更多可供使用的空间
  • 可配置行细节区域,从而只为选择的行显示该区域,当不需要时允许用户折叠额外的细节
<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <Border BorderBrush="SteelBlue" CornerRadius="5">
            <TextBlock Text="{Binding Path=Description}" TextWrapping="Wrap" />
        </Border>
    </DataTemplate>
</DataGrid.RowDetailsTemplate>
冻结列

冻结列必须位于网格的左侧,通过设置 ForzenColumnCount 属性来决定冻结的列数量。

<DataGrid ForzenColumnCount="1"/>
排序

DataGrid 控件内置了排序功能,只要绑定到实现了 IList 接口的集合(List和ObservableCollection),DataGrid控件就可以自动获得排序功能。

用户单击列头,可以根据此列进行排序;按住Shift键可以根据多列进行排序。

编辑

DataGrid控件以几种方式限制编辑功能:

  • DataGrid.IsReadOnly - 值为true时不能编辑
  • DataGridColumn.IsReadOnly - 值为true时,不能编辑该列
  • 只读属性 - 如果数据对象的属性没有 set 方法,不能编辑该列

当单元格切换到编辑模式时发生的变化取决于列的类型。DataGridTextColumn显示文本框,DataGridCheckBox 列显示复选框,下面显示 DataPicker控件:

<DataGridTemplateColumn Header="Date Added">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=DateAdded, Converter={StaticResource DateOnlyConverter}}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <DatePicker SelectedDate="{Binding Path=DateAdded, Mode=TwoWay}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

DataGrid支持基本验证系统,当数据绑定中出问题和属性设置器抛出异常会显示红色外边框。可以通过 ValidationRules 对数据的合法性进行验证。

除此之外,也可以通过其他几种方法进行验证:

方法名说明
BeginningEdit当单元格进入编辑模式时发生
PreparingCellForEdit用于模板列
CellEditEnding当单元格正退出编辑模式时发生
RowEnditEnding当用户在编辑完当前行之后导航到新行时发生
我的公众号

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值