在WPF中筛选DataGrid

ltqd579y  于 2023-05-08  发布在  其他
关注(0)|答案(7)|浏览(297)

我在数据网格中加载了一个对象列表:

dataGrid1.Items.Add(model);

model成为数据库中的数据。它有Id(int)Name(string)Text(string)
在我的数据网格中,我只显示model的名称。当我在文本框中输入内容时,我现在如何过滤数据网格?
我在这个页面:http://msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx但我不明白那里的代码,我不能解释我应该如何转置我的问题。

zyfwsgd6

zyfwsgd61#

有多种方法可以筛选集合
让我们建议这是您的项目类

public class Model
{
    public string Name
    {
        get;
        set;
    }
}

你的收藏看起来

var ObColl = new ObservableCollection<Model>();

        ObColl.Add(new Model() { Name = "John" });
        ObColl.Add(new Model() { Name = "Karl" });
        ObColl.Add(new Model() { Name = "Max" });
        ObColl.Add(new Model() { Name = "Mary" });

方式1(Predicate):

public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your ObservableCollection
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        // your Filter
        var yourCostumFilter= new Predicate<object>(item => ((Model)item).Name.Contains("Max"));

        //now we add our Filter
        Itemlist.Filter = yourCostumFilter;

        dataGrid1.ItemsSource = Itemlist;
    }

方式2(FilterEventHandler):

public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your Filter
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

       //now we add our Filter
       _itemSourceList.Filter += new FilterEventHandler(yourFilter);

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        dataGrid1.ItemsSource = Itemlist;
    }

    private void yourFilter(object sender, FilterEventArgs e)
    {
        var obj = e.Item as Model;
        if (obj != null)
        {
            if (obj.Name.Contains("Max"))
                e.Accepted = true;
            else
                e.Accepted = false;
        }
    }

扩展信息到Way 1

如果需要多个条件或一些复杂的过滤器,您可以向Predicat添加一个方法

// your Filter
    var yourComplexFilter= new Predicate<object>(ComplexFilter);

    private bool ComplexFilter(object obj)
    {
        //your logic
    }
lawou6xi

lawou6xi2#

这是使用ICollectionView的Filter属性的简单实现。假设您的XAML包含以下内容:

<TextBox x:Name="SearchTextBox" />
<Button x:Name="SearchButton"
        Content="Search"
        Click="SearchButton_OnClick"
        Grid.Row="1" />
<DataGrid x:Name="MyDataGrid"
          Grid.Row="2">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Lorem ipsum column"
                            Binding="{Binding}" />
    </DataGrid.Columns>
</DataGrid>

然后在构造函数中,你可以得到你的数据的默认视图,在那里你可以设置过滤 predicate ,它将对你的集合中的每一个项目执行。CollectionView不知道什么时候应该更新集合,所以必须在用户单击搜索按钮时调用Refresh。

private ICollectionView defaultView;

public MainWindow()
{
    InitializeComponent();

    string[] items = new string[]
    {
        "Asdf",
        "qwer",
        "sdfg",
        "wert",
    };

    this.defaultView = CollectionViewSource.GetDefaultView(items);
    this.defaultView.Filter =
        w => ((string)w).Contains(SearchTextBox.Text);

    MyDataGrid.ItemsSource = this.defaultView;
}

private void SearchButton_OnClick(object sender, RoutedEventArgs e)
{
    this.defaultView.Refresh();
}

在此url中,您可以找到CollectionViews的更详细描述:http://wpftutorial.net/DataViews.html

kd3sttzy

kd3sttzy3#

@WiiMaxx,不能评论为没有足够的代表。我会对那里的直接演员更加小心。它们可能会因为一件事而变慢,如果将相同的过滤器应用于包含不同复杂类型数据的网格,则会出现InvalidCastException。

// your Filter
    var yourCostumFilter= new Predicate<object>(item =>
    {
        item = item as Model;
        return item == null || item.Name.Contains("Max");
    });

这不会破坏您的数据网格,并且在强制转换失败时不会过滤结果。如果代码出错,对用户的影响更小。最重要的是,由于“as”操作符不像直接强制转换操作那样执行任何显式的类型强制转换,因此过滤器将更快。

apeeds0o

apeeds0o4#

看看DataBinding -->在你的例子中,不要向你的网格中添加项目,而是设置itemssource

<Datagrid ItemsSource="{Binding MyCollectionOfModels}" />

dataGrid1.ItemsSource = this._myCollectionOfModels;

如果你想要某种过滤、排序、分组,请看CollectionView

ewm0tg9j

ewm0tg9j5#

我发现了一个愚蠢的方法,知道这是一个古老的问题,但...只需在DataGrid对象的items属性上使用Filter函数。像这样:(对不起,我只学了VB)

Public Property SearchName As String
    Get
        Return _SearchName
    End Get
    Set
        _SearchName = Value
        DG_drw_overview.Items.Filter = New Predicate(Of Object)(Function(x) x.Name.Contains(Value))           
    End Set
End Property

每次在文本框中键入内容时,此属性都会更改。DG_drw_overview是DataGrid示例。在Predicate中,对象表示您放入DataGrid中的对象。
然后将SearchName绑定到文本框

<TextBox x:Name="TB_search" 
         Text="{Binding SearchName, UpdateSourceTrigger=PropertyChanged}"/>

将文本框的dataContext设置为主类(通常在InitializeComponent()之后)

TB_search.DataContext = Me
mwg9r5ms

mwg9r5ms6#

把这个留在这里,以防像我一样,你不能让上面的其他方法正常工作。

//Example of my Transaction class
//Transaction(ID, Amount, Description)

ListCollectionView collectionView = new ListCollectionView(List<Transaction>);
collectionView.Filter = (e) =>
{
    Transaction transaction = e as Transaction;
    if (transaction.Amount >= 0) //When this is true it returns all positive transactions
    {
       return true;
    }
    else
    {
       return false;
    }
};

dataGrid.ItemsSource = collectionView;
  • 我用if语句中的这个参数为datagrid做了一个combobox过滤器。
  • 组合框有3个选项Credit/Debit/Credit & Debit,这取决于我选择的选项,它将过滤选择更改事件
  • 我从这里得到这个:http://dotnetpattern.com/wpf-datagrid-filtering
4bbkushb

4bbkushb7#

可以使用dataview筛选器来筛选datagrid行。

DataView dv = datatable.DefaultView;
StringBuilder sb = new StringBuilder();
foreach (DataColumn column in dv.Table.Columns)
{
    sb.AppendFormat("[{0}] Like '%{1}%' OR ", column.ColumnName, "FilterString");
}
sb.Remove(sb.Length - 3, 3);
dv.RowFilter = sb.ToString();
dgvReports.ItemsSource = dv;
dgvReports.Items.Refresh();

其中“datatable”是提供给数据网格的数据源,使用字符串构建器构建过滤器查询,其中“Filter String”是要在数据网格中搜索的文本,并将其设置为dataview,最后将dataview设置为数据网格的itemsource并刷新它。

相关问题