WPF之DataGrid的使用及案例

WPF之DataGrid的使用及案例

1.参考资料

官方文档:DataGrid - WPF .NET Framework | Microsoft Learn

2.DataGrid的数据源绑定

绑定viewModel中的数据源,设置itemSource属性即可,dataGrid会根据绑定的属性自动生成表头。绑定类型为IList。

<DataGrid Name="DataGrid" ItemsSource="{Binding Students}"/>

注意:如果想使用自定义的表头和内容,则需要关闭自动生成列表(设置AutoGenerateColumns​ = false),否则二者会同时出现。

3.常用属性的设置

官方文档里有写,这里省略。

在这里插入图片描述

补充:

  • GridLinesVisibility​,设置是否显示表格横竖线
  • 生成的表格中默认会有一个空白行用于添加新数据,如果不想要可以关闭,设置CanUserAddRows = False

4.自定义单元格Template

有四种列形式,如下图
在这里插入图片描述

text用于显示文本框,checkBox显示多选框,Combox复选框,hyperLink超链接。

除去默认的控件以外,还支持自定义单元格,使用DataGridTemplateColumn​,如图,我在白表格中添加了一个按钮用于修改数据。

在这里插入图片描述

<DataGrid Name="DataGrid" ItemsSource="{Binding Students}"
                      SelectedItems="{Binding SelectedItems}"
                      VerticalContentAlignment="Center"
                      AutoGenerateColumns="False" 
                      GridLinesVisibility="Horizontal" 
                      AlternationCount="2"
                      AlternatingRowBackground="LightGray" 
                      CanUserAddRows="False">
                <DataGrid.Columns> 
                    <DataGridTextColumn Header="姓名" Binding="{Binding UserName}"></DataGridTextColumn>
                    <DataGridTextColumn Header="年龄" Binding="{Binding userAge}"></DataGridTextColumn>
                    <DataGridTextColumn Header="地址" Binding="{Binding UserAddress}"></DataGridTextColumn>
                    <DataGridTextColumn Header="手机号" Binding="{Binding UserNumber}"></DataGridTextColumn>
                    <DataGridCheckBoxColumn Header="多选"></DataGridCheckBoxColumn>
                    <DataGridTemplateColumn Width="auto">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button>点击修改</Button>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>

5.常见用法

5.1.多选框,批量删除,右键菜单编辑,添加新数据,显示图片

实现的关键在于获取到多选的内容,wpf提供了一个Selecteditem(s)来获取选中的行的值,也可以获取单个表格的值(SelectedItemCell).由于这个值是只读属性,无法使用Binding来获取到。所以,可以使用代码来获取。

界面布局:

在这里插入图片描述

代码:

<Window.DataContext>
    <vm:MainViewModel/>
</Window.DataContext>

<Window.Resources>
    <ContextMenu x:Key="DataGridContextMenu">
        <MenuItem Name="edit"  Header="编辑" Click="edit_Click"/>
    </ContextMenu>
</Window.Resources>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="8*"/>
        <RowDefinition Height="2*"/>
    </Grid.RowDefinitions>

    <DataGrid x:Name="studentData" Grid.Row="0" Height="auto" CanUserDeleteRows="False"
              ContextMenu="{StaticResource DataGridContextMenu}"
              ItemsSource="{Binding CollectionsDisplay}" AutoGenerateColumns="False" CanUserAddRows="False">
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="LightGray"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" Binding="{Binding userId}" IsReadOnly="True"/>
            <DataGridTextColumn Header="用户名" Binding="{Binding userName}" IsReadOnly="True" />
            <DataGridTextColumn Header="地址" Binding="{Binding userAddress}" IsReadOnly="True" />
            <DataGridTextColumn Header="邮箱" Binding="{Binding userEmail}" IsReadOnly="True"/>
            <DataGridCheckBoxColumn Header="多选" IsReadOnly="False" CanUserSort="False" Binding="{Binding isChecked}" >
                <DataGridCheckBoxColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox VerticalContentAlignment="Center" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.IsAllSelected}"/>
                            <Label>全选</Label>
                        </StackPanel>
                    </DataTemplate>
                </DataGridCheckBoxColumn.HeaderTemplate>
            </DataGridCheckBoxColumn>
            <DataGridTextColumn Width="*"></DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>

    <StackPanel Grid.Row="1" Orientation="Horizontal">
        <StackPanel.Resources>
            <Style TargetType="Button">
                <Setter Property="Height" Value="20"></Setter>
                <Setter Property="Margin" Value="5 0 0 0"></Setter>
            </Style>
        </StackPanel.Resources>
        <Button Command="{Binding DeleteItemsCommand}">删除</Button>
        <Button Command="{Binding NextPageCommand}">下一页</Button>
        <TextBox Margin="5 0 0 0" Height="20" Width="40" Text="{Binding PageNum}"></TextBox>
        <TextBlock Margin="5 0 0 0" Height="20" Width="40">
            <TextBlock.Text>
                <MultiBinding StringFormat="{}{0}/{1}页">
                    <Binding Path="PageNum"/>
                    <Binding Path="TotalPage"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
        <Button Command="{Binding GotoPageCommand}">转到</Button>
    </StackPanel>
</Grid>

1.多选框的实现

使用自定义模板,使用checkBox作为表头。checkBox绑定了ViewModel中的一个值并重写OnPropertyChanged方法,在发生变化时,更改所有item的isChecked的值。

<DataGridCheckBoxColumn Header="多选" IsReadOnly="False" CanUserSort="False" Binding="{Binding isChecked}" >
                <DataGridCheckBoxColumn.HeaderTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <CheckBox VerticalContentAlignment="Center" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.IsAllSelected}"/>
                            <Label>全选</Label>
                        </StackPanel>
                    </DataTemplate>
                </DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>

代码:

//重写方法
partial void OnIsAllSelectedChanged(bool value)
{
    foreach (var item in CollectionsDisplay)
    {
        item.isChecked = value;
    }
	//更新界面
    CollectionsDisplay = new ObservableCollection<Student>(CollectionsDisplay);
}

2.批量删除

找出所有isChecked的值(使用LINQ),然后将其删除即可。

var items = CollectionsDisplay.Where(m => m.isChecked == true);
if (items.Any())
{
    foreach (var item in items)
    {
        Collections.Remove(item);
    }
    CollectionsDisplay = new ObservableCollection<Student>(Collections.Take(PageSize));
}

3.右键菜单修改

<Window.Resources>
    <ContextMenu x:Key="DataGridContextMenu">
        <MenuItem Name="edit"  Header="编辑" Click="edit_Click"/>
    </ContextMenu>
</Window.Resources>

右键菜单,绑定了一个点击事件,该事件打开一个dialog用于更新数据。打开window时需要传递当前选择的item的值,这里使用构造方法传入。在dialog接收到传入的值后,将其传入他的viewModel,并绑定它。为了实现不同的值的修改效果,可以使用converter将传放入的obj转换成字典类以实现复用效果。

​​在这里插入图片描述

ps:关于使用converter转换字典类的实现方式

1.使用反射,使用反射获取到属性名和值装入字典类

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var info = value.GetType().GetProperties();
    var dic = new Dictionary<string, object>();
    foreach(var item in info)
    {
        dic.Add(item.Name,item.GetValue(value));
    }
    return dic;
}

2.使用JsonSerialzer先序列化再反序列化成字典类

使用这种方式可以使用源生成器自定义序列化后的属性别名,这样在生成字典类后可以显示属性别名而非属性名

属性别名:

class Student
{
    [JsonPropertyName("用户ID")]
    public int UserId { get; set; }
    [JsonPropertyName("用户名")]
    public string? UserName { get; set; }
    [JsonPropertyName("用户地址")]
    public string? UserAddress { get; set; }
    [JsonPropertyName("用户创建时间")]
    public DateTimeOffset UserCreateTime { get; set; }
}
var stu = new Student()
{
    UserId = 1,
    UserName = "张三",
    UserAddress = "浙江省杭州市萧山区",
    UserCreateTime = DateTimeOffset.Now
};
JsonSerialzer.Serialze(stu);
//结果:
//{
//  "用户ID": 1,
//  "用户名": "张三",
//  "用户地址": "浙江省杭州市萧山区",
//  "用户创建时间": "2024-05-28T16:17:41.7146546\u002B08:00"
//}

4.显示图片

使用自定义模板

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Image Source="xxx"></Image>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

5.2.使用DataGrid实现分页

其中一种思路

页面布局:

请添加图片描述

页面代码:

<Button Command="{Binding NextPageCommand}">下一页</Button>
<TextBox Margin="5 0 0 0" Height="20" Width="40" Text="{Binding PageNum}"></TextBox>
<TextBlock Margin="5 0 0 0" Height="20" Width="40">
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0}/{1}页">
            <Binding Path="PageNum"/>
            <Binding Path="TotalPage"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>
<Button Command="{Binding GotoPageCommand}">转到</Button>

viewModel中的定义:

//原始数据
public List<Student> Collections { get; set; } = [];
//用于显示的数据
[ObservableProperty] private ObservableCollection<Student> _collectionsDisplay = [];
//当前页码
[ObservableProperty] private int _pageNum = 1;
//总页码
[ObservableProperty] private int _totalPage;

实现思路是,可以根据每页显示的数量和当前的页码,可以计算出当前需要显示的是哪些条目。

1.页面跳转

if (PageNum >= 1)
	//跳过之前的条目,然后拿到固定数目的数据即为当前页的数据,然后更新页面
    CollectionsDisplay = new ObservableCollection<Student>(Collections.Skip((PageNum - 1) * PageSize).Take(PageSize));

2.下一页

PageNum++;
CollectionsDisplay = new ObservableCollection<Student>(Collections.Skip((PageNum - 1) * PageSize).Take(PageSize));

5.3.实现数据按条件筛选

使用LINQ筛选出需要的数据然后显示到表中即可。

### 回答1: 在WPF使用DataGrid实现列筛选可以通过以下步骤进行操作: 1. 创建一个DataGrid控件并绑定数据源,例如一个ObservableCollection对象。 2. 为DataGrid的列头部创建筛选器控件,可以使用ComboBox、TextBox或者其他适合的控件类型。可以为每一列的列头部创建一个筛选器控件,也可以在一个指定的位置创建一个通用的筛选器控件。 3. 在筛选器控件中做相应的改动来筛选网格中的数据。例如,在ComboBox控件中提供选项供用户选择,或是在TextBox中输入的文字来进行筛选操作。 4. 在筛选器控件的值改动时,使用筛选条件对数据源中的数据进行过滤操作。可以使用LINQ表达式或者其他筛选技术来完成这一步骤。 5. 可以通过绑定筛选器控件的SelectedValue属性或者TextChanged事件来实时触发筛选操作。 6. 在筛选数据后,更新DataGrid的显示结果,例如重新绑定数据源或者手动更改DataGrid的ItemsSource属性。 7. 在需要的时候,可以为DataGrid添加分页功能,使得用户可以翻页浏览筛选后的数据。 以上仅为基本步骤,具体实现操作可以根据不同的需求和情况进行调整。希望以上回答对您有帮助! ### 回答2: 在WPF中,使用DataGrid可以实现列筛选的功能。要实现列筛选,可以按照以下步骤进行: 1. 在XAML文件中创建一个DataGrid,并定义需要显示的列。 ```xaml <DataGrid x:Name="MyDataGrid"> <DataGrid.Columns> <DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <DataGridTextColumn Header="年龄" Binding="{Binding Age}" /> <DataGridTextColumn Header="性别" Binding="{Binding Gender}" /> </DataGrid.Columns> </DataGrid> ``` 2. 在代码中为DataGrid添加筛选功能。可以使用TextBox和按钮来实现筛选功能。 ```csharp private void FilterButton_Click(object sender, RoutedEventArgs e) { // 获取筛选条件 string filterText = FilterTextBox.Text; // 创建一个CollectionView ICollectionView view = CollectionViewSource.GetDefaultView(MyDataGrid.ItemsSource); // 添加筛选条件 view.Filter = item => { // 判断是否满足筛选条件 if (item is YourDataType data) { return data.Name.Contains(filterText) || data.Age.ToString().Contains(filterText) || data.Gender.Contains(filterText); } return false; }; // 刷新DataGrid view.Refresh(); } ``` 3. 在XAML中创建TextBox和按钮,并绑定对应的事件处理程序。 ```xaml <StackPanel> <TextBox x:Name="FilterTextBox" Width="200" /> <Button Content="筛选" Click="FilterButton_Click" /> </StackPanel> ``` 这样,当用户输入筛选条件,并点击筛选按钮时,DataGrid会根据条件对数据进行筛选,并只显示满足条件的行。 ### 回答3: WPF(Windows Presentation Foundation)是一种用于创建可视化Windows应用程序的框架。DataGridWPF中一个常用的控件,用于在界面上显示和编辑数据。 要实现列筛选,可以使用DataGrid中的内置功能和一些自定义代码。以下是一种实现方式: 1. 首先,在XAML文件中定义一个DataGrid控件,并设置AutoGenerateColumns属性为False,这样可以手动定义DataGrid的列。 2. 在每个列的HeaderTemplate中添加一个TextBox控件,用于接收用户输入的筛选条件。 3. 在代码-behind中,使用DataGrid的AutoGeneratingColumn事件来为每个列添加一个过滤器。 4. 在过滤器中,获取用户输入的筛选条件,并根据条件过滤DataGrid中的数据。 以下是一个简单的实例代码: XAML文件: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Data}"> <DataGrid.Columns> <DataGridTextColumn Header="Name"> <DataGridTextColumn.HeaderTemplate> <DataTemplate> <TextBox TextChanged="Filter_TextChanged" /> </DataTemplate> </DataGridTextColumn.HeaderTemplate> </DataGridTextColumn> <!-- 添加其他列 --> </DataGrid.Columns> </DataGrid> </Window> 代码-behind文件: public partial class MainWindow : Window { public ObservableCollection<DataItem> Data { get; set; } public MainWindow() { InitializeComponent(); Data = new ObservableCollection<DataItem>(); // 添加数据到Data集合中 dataGrid.ItemsSource = Data; dataGrid.AutoGeneratingColumn += DataGrid_AutoGeneratingColumn; } private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { // 为每个列添加过滤器 e.Column.HeaderTemplate = (DataTemplate)FindResource("FilterColumnHeaderTemplate"); } private void Filter_TextChanged(object sender, TextChangedEventArgs e) { // 获取筛选条件 var input = ((TextBox)sender).Text; // 根据条件过滤DataGrid中的数据 dataGrid.ItemsSource = Data.Where(item => item.Name.Contains(input)); } } DataItem类是一个简单的数据模型,具有Name等属性。 此实现方式允许用户通过输入文本框中的条件来筛选DataGrid中的列。根据输入的条件,将仅显示满足条件的数据。可以按需添加更多的列以及适合的筛选条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值