如何在数据表中进行列名过滤?使用C#,WPF

xjreopfe  于 2023-03-24  发布在  C#
关注(0)|答案(2)|浏览(125)

我想做一个数据表,它是根据列名过滤的。下面是我想要的:

我想点击类型,只有“A”,“B”,“C”。所以我只能看到选定的类型内容。
嗯,像这个。

,但只在列名。最高列。
我使用C#,.NET 6.0,WPF。
你能给我看一些简单或复杂的C#和WPF代码吗?我对它了解不多,但继续学习。

lzfw57am

lzfw57am1#

示例:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Core2022.SO.nojob
{
    public enum TypeEnum
    { A, B, C }

    public class RowEntity
    {
        public string Name { get; set; } = string.Empty;

        public TypeEnum Type { get; set; }
    }

    public class TableVM
    {
        public ObservableCollection<RowEntity> Rows { get; } = new();

        public TypeEnum? SelectedType { get; set; }

        public static IReadOnlyList<TypeEnum> Types { get; } = Array.AsReadOnly((TypeEnum[])Enum.GetValues(typeof(TypeEnum)));
    }
}
<Window x:Class="Core2022.SO.nojob.ColumnFilterWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Core2022.SO.nojob"
        mc:Ignorable="d"
        Title="ColumnFilterWindow" Height="450" Width="800"
        DataContext="{DynamicResource vm}">
    <Window.Resources>
        <local:TableVM x:Key="vm">
            <local:TableVM.Rows>
                <local:RowEntity Name="first" Type="B"/>
                <local:RowEntity Name="second" Type="A"/>
                <local:RowEntity Name="third" Type="C"/>
                <local:RowEntity Name="fourth" Type="B"/>
                <local:RowEntity Name="fifth" Type="A"/>
                <local:RowEntity Name="sixth" Type="C"/>
                <local:RowEntity Name="seventh" Type="B"/>
                <local:RowEntity Name="eighth" Type="A"/>
                <local:RowEntity Name="ninth" Type="C"/>
                <local:RowEntity Name="tenth" Type="B"/>
                <local:RowEntity Name="eleventh" Type="A"/>
                <local:RowEntity Name="twelfth" Type="C"/>
            </local:TableVM.Rows>
        </local:TableVM>
    </Window.Resources>
    <Grid>
        <DataGrid x:Name="dGrid"
                  ItemsSource="{Binding Rows}"
                  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
                <DataGridComboBoxColumn SelectedItemBinding="{Binding Type}"
                                        ItemsSource="{x:Static local:TableVM.Types}">
                    <DataGridComboBoxColumn.Header>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="TYPE"/>
                            <ComboBox x:Name="cBox" ItemsSource="{x:Static local:TableVM.Types}"
                                      SelectionChanged="OnTypeSelectionChanged"
                                      SelectedItem="{Binding SelectedType, Source={StaticResource vm}}"/>
                            <Button Content="❌" Foreground="Red" FontWeight="ExtraBold"
                                    Click="OnClearClick"/>
                        </StackPanel>
                    </DataGridComboBoxColumn.Header> 
                </DataGridComboBoxColumn>
            </DataGrid.Columns>

        </DataGrid>
    </Grid>
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace Core2022.SO.nojob
{
    public partial class ColumnFilterWindow : Window
    {
        public ColumnFilterWindow()
        {
            InitializeComponent();
        }

        private void OnTypeSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Selector selector = (Selector)sender;
            if (selector.SelectedItem is TypeEnum type)
            {
                dGrid.Items.Filter = item =>
                {
                    return item is RowEntity rowEntity &&
                           rowEntity.Type == type;
                };
            }
            else
            {
                dGrid.Items.Filter = null;
            }
        }

        private void OnClearClick(object sender, RoutedEventArgs e)
        {
            cBox.SelectedIndex = -1;
        }
    }
}
hrysbysz

hrysbysz2#

您总是通过将筛选器表达式分配给其关联的ICollectionView.Filter属性来筛选ItemsControl(如DataGrid)。
为此,您可以通过访问ItemsControl.Items属性来检索ItemsControlICollectionView(如果您可以直接访问ItemsControl示例)。
否则,您可以始终使用静态帮助器方法CollectionViewSource.GetDefaultView(mySourceCollection),这当然需要直接引用源集合(例如在数据绑定场景中)。
假设您有一个ComboBox来选择筛选 predicate ,例如string值或enum值(无论Type属性/列的数据类型是什么),以及DataGrid,其通过绑定到具有属性NameContentTypeExceptions,一个非常简单的解决方案可以如下所示:
在代码隐藏中处理ComboBox.SelectionChanged事件

private void OnComboBoxSelectedItemChanged(object sender, EventArgs e)
{
  var comboBox = sender as ComboBox;
  var selectedColumnValue = comboBox.SelectedItem as string;

  // ICollectionView.Filter is of type 'Predicate<object>',
  // so we can assign a simple lambda expression as filter predicate.
  // The predicate must return 'true' if the tested item must be displayed.
  this.DataGridView.Items.Filter = item => (item as MyRowItem).Type == selectedColumnValue;
}
<Window>
  <StackPanel>
    <DataGrid x:Name="DataGridView" />
    <ComboBox SelectionChanged="OnComboBoxSelectedItemChanged" />
  </StackPanel>
</Window>

理解集合视图的概念很重要。WPF绑定引擎将引用集合的集合视图,而不是集合本身:集合视图。
即使您在本地分配源集合,而没有任何数据绑定到ItemsControl.ItemsSourceItemsControl也会在内部向绑定引擎注册该集合,以便跟踪更改。
因此,为了提高性能,您应该始终将实现INotifyCollectionChanged的集合(例如ObservableCollection)分配给ItemsControl.ItemsSource属性。

相关问题