WPF 入门教程 DataGrid数据绑定

介绍

自 .NET 4.0 以来,Microsoft 提供了一个 DataGrid 控件,该控件提供了所需的所有基本功能,例如:

  • 自动生成列
  • 手动定义列
  • 选择
  • 分组
  • 列排序、重新排序和调整大小
  • 行详细信息
  • 交替背景画笔
  • 冻结列
  • 标题可见性
  • 如何对自动生成的列进行模板化

基本用法:自动生成列

要显示基本数据网格,只需将 DataGrid 控件拖放到您的视图中并将其绑定 ItemsSource 到数据对象集合即可。DataGrid 提供了一项称为 AutoGenerateColumns 根据数据对象的公共属性自动生成列的功能。它生成以下类型的列:

  • 字符串值的文本框列
  • 布尔值的复选框列
  • 可枚举值的组合框列
  • Uri 值的超链接列
<DataGrid ItemsSource="{Binding Customers}" />

推荐一款好用的WPF MVVM框架开源控件库 Newbeecoder.UI

https://www.zhihu.com/video/1514766555765846016

手动定义列

AutoGenerateColumns 或者,您可以通过将属性设置为 来手动定义列 False Columns 在这种情况下,您必须在数据网格的集合中定义列。您可以使用以下类型的列:

  • DataGridCheckBoxColumn 对于布尔值
  • DataGridComboBoxColumn 对于可枚举的值
  • DataGridHyperlinkColumn 对于 Uri 值
  • DataGridTemplateColumn 通过定义您自己的单元格模板来显示任何类型的数据
  • DataGridTextColumn 显示文本值
<DataGrid ItemsSource="{Binding Customers}" AutoGenerateColumns="False" >
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Source="{Binding Image}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

选择

数据网格包括多种选择模式。它们由 SelectionMode and SelectionUnit 属性配置。

  • SelectionMode 可以设置 Single Extended 定义是否可以同时选择一个或多个单位。
  • 定义了一个选择单元的 SelectionUnit 范围。它可以设置为 Cell , CellAndRowHeader FullRow
<Da​​taGrid ItemsSource = "{Binding Customers}"  
SelectionMode = "Extended" SelectionUnit = "Cell" /> 

列排序、重新排序和调整大小

数据网格提供了对列进行排序、重新排序和调整大小的功能。它们可以通过以下属性启用或禁用:

  • CanUserReorderColumns 启用或禁用列重新排序
  • CanUserResizeColumns 启用或禁用列大小调整
  • CanUserResizeRows 启用或禁用行大小调整
  • CanUserSortColumns 启用或禁用列排序
<Da​​taGrid  ItemsSource = "{Binding Customers}"  
CanUserReorderColumns = "True" CanUserResizeColumns = "True" CanUserResizeRows = "False" CanUserSortColumns = "True" />

分组

数据网格还支持分组。要启用分组,您必须定义一个包含至少一个GroupDescription的CollectionView,该GroupDescription定义如何分组的标准。

Customers = new ListCollectionView(_customers);
Customers.GroupDescriptions.Add(new PropertyGroupDescription("Gender"));

您需要做的第二件事是定义组应该是什么样子的模板。你可以将GroupStyle设置为如下代码段。

<DataGrid ItemsSource="{Binding GroupedCustomers}">
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Path=Name}" />
                    </StackPanel>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander>
                                    <Expander.Header>
                                        <StackPanel Orientation="Horizontal">
                                          <TextBlock Text="{Binding Path=Name}" />
                                          <TextBlock Text="{Binding Path=ItemCount}"/>
                                          <TextBlock Text="Items"/>
                                        </StackPanel>
                                    </Expander.Header>
                                    <ItemsPresenter />
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
</DataGrid>

行详细信息

数据网格提供了显示所选行的详细信息面板的功能。可以通过将 DataTemplate 设置为 RowDetailsTemplate 属性来启用它。数据模板通过DataContext获取绑定到这一行的对象,并可以绑定到它。

<DataGrid ItemsSource="{Binding Customers}">
    <DataGrid.Columns>
    <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <Image Height="100" Source="{Binding Image}" />
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>


public class GenderTemplateSelector : DataTemplateSelector
    public DataTemplate MaleTemplate { get; set; }
    public DataTemplate FemaleTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, 
                  DependencyObject container)
        var customer = item as Customer;
        if (customer == null)
            return base.SelectTemplate(item, container);
        if( customer.Gender == Gender.Male)
            return MaleTemplate;
        return FemaleTemplate;


<l:GenderTemplateSelector x:Key="genderTemplateSelector">
    <l:GenderTemplateSelector.MaleTemplate>
        <DataTemplate>
            <Grid Background="LightBlue">
                <Image Source="{Binding Image}" Width="50" />
            </Grid>
        </DataTemplate>
    </l:GenderTemplateSelector.MaleTemplate>
    <l:GenderTemplateSelector.FemaleTemplate>
        <DataTemplate>
            <Grid Background="Salmon">
                <Image Source="{Binding Image}" Width="50" />
            </Grid>
        </DataTemplate>
    </l:GenderTemplateSelector.FemaleTemplate>
</l:GenderTemplateSelector>
<DataGrid ItemsSource="{Binding Customers}" 
          RowDetailsTemplateSelector="{StaticResource genderTemplateSelector}" />

交替背景画笔

您可以定义一个 AlternatingRowBackground 应用于每个偶数行。 AlternationCount 如果您只想对每第 n 个数据行进行墨迹书写,您可以另外指定一个。

 <Da​​taGrid ItemsSource = "{Binding Customers}" AlternatingRowBackground = "Gainsboro" AlternationCount = "2" />    

冻结列

数据网格还支持冻结列的功能。这意味着当您水平浏览所有列时,它们会保持可见。这是一个有用的功能,可以让引用列(如 ID 或名称)始终可见,以在滚动时保持方向。

要冻结许多列,只需将FrozenColumnCount属性设置为要冻结的列数。

<Da​​taGrid  ItemsSource = "{Binding Customers}" FrozenColumnCount = "2"   />

标题可见性

您可以通过将 HeadersVisibility 属性设置为 None Row ColumnAll

 <Da​​taGrid  ItemsSource = "{Binding Customers}"  HeadersVisibility = "None"  />  

如何对自动生成的列进行模板化

如果您想使用 自动生成列 AutoGenerateColumns="True" ,则不能使用 CellTemplates ,因为 DataGrid 自动生成文本、组合、超链接或复选框列,但这些都不是可模板化的。一个简单的解决方法是挂钩自动生成,取消它并始终创建一个 DataGridTemplateColumn . 以下片段显示了这个想法(代码只是草稿):

public class MyDataGrid : DataGrid
    public DataTemplateSelector CellTemplateSelector
        get { return (DataTemplateSelector)GetValue(CellTemplateSelectorProperty); }
        set { SetValue(CellTemplateSelectorProperty, value); }
    public static readonly DependencyProperty CellTemplateSelectorProperty =
        DependencyProperty.Register("Selector", typeof(DataTemplateSelector), typeof(MyDataGrid), 
        new FrameworkPropertyMetadata(null));
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
        e.Cancel = true;
        Columns.Add(new DataGridTemplateColumn