WPF: Filtering a dataGrid on the fly

无人久伴 提交于 2021-01-24 18:09:45

问题


In my WPF Window I have a DataGrid control, with its ItemsSource bound to an ObservableCollection of items (let's say a simple object with a couple properties):

XAML: (Removed some xmlns stuff for brevity)

<Window>
    <Window.Resources>
        <CollectionViewSource x:Key="MyViewSource"
                              Source="{Binding MyItemList}"
                              Filter="MyItemList_Filter"/>
    </Window.Resources>

    <Window.DataContext>
        <!-- Some Ioc stuff -->
    </Window.DataContext>

    <StackPanel>
        <TextBox Text="{Binding TextFilter}" />
        <DataGrid Grid.Row="1" x:Name="dataGrid"
            ItemsSource="{Binding Source={StaticResource MyViewSource}}"
            SelectionUnit="FullRow"
            SelectionMode="Extended"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            HeadersVisibility="Column" />
    </StackPanel>
</Window>

ViewModel (cs):

public class ViewModel : ViewModelBase // From Galasoft MVVM Light toolkit
{

    #region TextFilter Property
    public const string TextFilterPropertyName = "TextFilter";

    private string _TextFilter;

    public string TextFilter
    {
        get
        {
            return _TextFilter;
        }

        set
        {
            if (_TextFilter == value)
            {
                return;
            }

            _TextFilter = value;

            RaisePropertyChanged(TextFilterPropertyName);
        }
    }
    #endregion // TextFilter Property

    #region MyItemList Property
    public const string MyItemListPropertyName = "MyItemList";

    private ObservableCollection<Item> _MyItemList;

    public ObservableCollection<Item> MyItemList
    {
        get
        {
            return _MyItemList;
        }

        set
        {
            if (_MyItemList == value)
            {
                return;
            }

            _MyItemList = value;

            RaisePropertyChanged(MyItemListPropertyName);
        }
    }
    #endregion // MyItemList Property


}

Filter method, from Window's code behind:

private void MyItemList_Filter(object sender, FilterEventArgs e)
{
    var vm = (ViewModel)this.DataContext;
    var item = (Item)e.Item;
    // ...Simplified...
    e.Accepted = item.PropertyToCheck.Contains(vm.TextFilter);
}

Filtering is applied only when filling MyItemList: how can I make the MyItemList_Filter be called (and DataGrid items be shown/hidden accordingly) on "live" TextFilter change?

Any help would be appreciated


回答1:


You could (should) move the filtering logic to the view model, e.g.:

public class ViewModel : ViewModelBase
{
    public const string TextFilterPropertyName = "TextFilter";

    private string _TextFilter;
    public string TextFilter
    {
        get
        {
            return _TextFilter;
        }
        set
        {
            if (_TextFilter == value)
                return;
            _TextFilter = value;
            RaisePropertyChanged(TextFilterPropertyName);
            Filter();
        }
    }

    public const string MyItemListPropertyName = "MyItemList";

    private ObservableCollection<Item> _MyItemList;
    public ObservableCollection<Item> MyItemList
    {
        get
        {
            return _MyItemList;
        }
        set
        {
            if (_MyItemList == value)
                return;

            _MyItemList = value;
            RaisePropertyChanged(MyItemListPropertyName);
        }
    }

    private ObservableCollection<Item> _filtered;
    public ObservableCollection<Item> FilteredList
    {
        get
        {
            return _filtered;
        }
        set
        {
            if (_filtered == value)
                return;

            _filtered = value;
            RaisePropertyChanged("FilteredList");
        }
    }

    private void Filter()
    {
        _filtered.Clear();
        foreach(var item in _MyItemList)
        {
            if (item.PropertyToCheck.Contains(TextFilter))
                _filtered.Add(item);
        }
    }
} 

That's where it belongs. Then you don't need to the CollectionViewSource:

<DataGrid Grid.Row="1" x:Name="dataGrid" ItemsSource="{Binding FilteredList}" ... />


来源:https://stackoverflow.com/questions/42232238/wpf-filtering-a-datagrid-on-the-fly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!