使用 TextBox 和 DatePicker 元素过滤 WPF DataGrid 行

Posted

技术标签:

【中文标题】使用 TextBox 和 DatePicker 元素过滤 WPF DataGrid 行【英文标题】:WPF DataGrid rows filtering using TextBox and DatePicker elements 【发布时间】:2021-12-09 04:38:06 【问题描述】:

我目前正在开发我的第一个 WPF 应用程序。我正在使用 .NET Framework 4.8。 在我的 WPF 应用程序中,我使用 DataGrid 元素。我这样定义我的 DataGrid 元素:

<DataGrid IsReadOnly="True" HeadersVisibility="Column" AutoGenerateColumns="False" Grid.Row="1" Grid.Column="0" x:Name="MyDataGrid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
    <DataGrid.Resources>
        <Style TargetType="x:Type DataGridColumnHeader">
            <Setter Property="Background" Value="Turquoise" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="BorderThickness" Value="0,0,1,2" />
            <Setter Property="BorderBrush" Value="Black" />
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="id" Binding="Binding id" Visibility="Hidden" Width="*"/>
        <DataGridTextColumn Header="fileId" Binding="Binding fileId" Visibility="Hidden" Width="*"/>
        <DataGridTextColumn Header="val1" Binding="Binding val1" Width="*"/>
        <DataGridTextColumn Header="val2" Binding="Binding val2, StringFormat=\0:dd.MM.yy\" Width="*"/>
        <DataGridTextColumn Header="val3" Binding="Binding val3, StringFormat=\0:dd.MM.yy\" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

此外,我还包括了两个日期选择器和一个文本框。我将这些定义如下:

<TextBox Grid.Row="0" IsReadOnly="False" Grid.Column="1"  Name="FilterVal1" TextChanged="FilterDataGrid"/>
<DatePicker Grid.Row="1" Grid.Column="1" Name="FilterVal2" SelectedDateChanged="FilterDataGrid"/>
<DatePicker Grid.Row="2" Grid.Column="1" Name="FilterVal3" SelectedDateChanged="FilterDataGrid"/>

在我的 FilterDataGrid 方法中,我现在按如下方式过滤 DataGrid 的行:

private void FilterDataGridKampagnen(object sender, object e)

    using (var ctx = new myEntities())
    
        var query = from k in ctx.MyTbl select k;
        var lstMyTbl = query.ToList();
        if(this.FilterVal1.Text.Trim().Length > 0)
        
            lstMyTbl = lstMyTbl.Where(x => x.val1.ToLower().Contains(this.FilterVal1.Text.ToLower())).ToList();
        

        if (FilterVal2.SelectedDate != null)
        
            lstMyTbl = lstMyTbl.Where(x => x.val2 >= FilterVal2.SelectedDate).ToList();
        

        if (FilterVal3.SelectedDate != null)
        
            lstMyTbl = lstMyTbl.Where(x => x.val3 <= FilterVal3.SelectedDate).ToList();
        

        this.MyDataGrid.ItemsSource = lstMyTbl;
    

我现在想知道这是否是为 DataGrid 元素实现过滤器的正确(推荐)方法?尤其是在过滤器之间应该存在 AND 关系的参考上,如果是空过滤器,则根本不应该考虑它。

【问题讨论】:

我认为“推荐”的方式是过滤绑定到 ItemsSource 属性的源集合,但从同一个集合中添加或删除项目或创建项目并不重要一个像你在这里做的新的。 你能给我一个例子,说明如何通过过滤 ItemSource 属性来过滤 DataGrid 吗? 唯一的区别是您基本上将代码移动到视图模型。您应该阅读 MVVM 设计模式。 【参考方案1】:

感谢mm8。这里可能“推荐”的解决方案是 MVVM 设计模式中的实现。我已经根据 MVVM 设计模式修改了我的代码。我的 DataGrid 元素看起来像这样(重要的是 ItemSource 与 ListData 的绑定。ListData 是根据 MVVM 设计模式的 ViewModel 中的列表。):

<DataGrid ItemsSource="Binding ListData" IsReadOnly="True" HeadersVisibility="Column" AutoGenerateColumns="False" Grid.Row="1" Grid.Column="0" x:Name="DataGridKampagnen" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
    <DataGrid.Resources>
        <Style TargetType="x:Type DataGridColumnHeader">
            <Setter Property="Background" Value="Turquoise" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="BorderThickness" Value="0,0,1,2" />
            <Setter Property="BorderBrush" Value="Black" />
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="id" Binding="Binding id" Visibility="Hidden" Width="*"/>
        <DataGridTextColumn Header="fileId" Binding="Binding fileId" Visibility="Hidden" Width="*"/>
        <DataGridTextColumn Header="val1" Binding="Binding val1" Width="*"/>
        <DataGridTextColumn Header="val2" Binding="Binding val2, StringFormat=\0:dd.MM.yy\" Width="*"/>
        <DataGridTextColumn Header="val3" Binding="Binding val3, StringFormat=\0:dd.MM.yy\" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

我的两个日期选择器和我的文本框如下所示:

<TextBox Grid.Row="0" IsReadOnly="False" Grid.Column="1"  Name="FilterVal1" Style="StaticResource FilterInput" Text="Binding Val1, UpdateSourceTrigger=PropertyChanged"/>
<DatePicker Grid.Row="1" Grid.Column="1" Name="FilterVal2" Style="StaticResource FilterInput" SelectedDate="Binding Val2"/>
<DatePicker Grid.Row="2" Grid.Column="1" Name="FilterVal3" Style="StaticResource FilterInput" SelectedDate="Binding Val3"/>

我为绑定到 ListData 提供数据的方法如下所示:

private List<MyTbl> GetMyTblLst()

    using (var ctx = new myEntities())
    
        var query = from k in ctx.MyTbl select k;
        var lstMyTbl = query.ToList();
        if(Val1.Trim().Length > 0)
        
            lstMyTbl = lstMyTbl.Where(x => x.val1.ToLower().Contains(Val1.ToLower())).ToList();
        

        if (Val2 != null)
        
            lstMyTbl = lstMyTbl.Where(x => x.val2 >= Val2).ToList();
        

        if (Val3 != null)
        
            lstMyTbl = lstMyTbl.Where(x => x.val3 <= Val3).ToList();
        

        return lstMyTbl;
    

到 ListData 的绑定是这样的:

public List<MyTbl> ListData => GetMyTblLst();

这种方法有效,并且是解决问题的一种非常干净且可重复使用的方法。

【讨论】:

以上是关于使用 TextBox 和 DatePicker 元素过滤 WPF DataGrid 行的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET 中 使用datepicker 日期选择的时候,如果INPUT控件或者TEXTBOX控件写了runat="server" 就无法调用

在 UpdatePanel 中使用 JQuery UI datepicker [重复]

如何在鼠标焦点上标记 DatePicker 和 Timepicker 中的所有文本

输入文本时 DatePicker.SelectedDate 不变

DatePicker 验证 Jquery 如何验证

自定义 WPF DatePickerTextBox 模板