使用WPF MVVM过滤datagrid,它可以工作,但我不知道为什么

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用WPF MVVM过滤datagrid,它可以工作,但我不知道为什么相关的知识,希望对你有一定的参考价值。

所以问题是,昨天我想制作一个用于过滤数据网格的搜索栏。我成功地做到了这一点但是当我今天看着它时,我意识到我不知道它为什么会起作用。这让我很困惑:

基本上我有一个datagrid,其ItemsSource设置为一个名为Equipments的ObservableCollection。为了过滤设备,我还创建了一个名为EquipmentView的ICollectionView,它只是我可以过滤的设备的镜像。

设备在我的数据库中的表中填充在viewmodel中,如下所示:

 public async Task LoadAsync()
    {
        try
        {
            var lookup = await _equipmentLookupDataService.GetEquipmentLookupAsync();
            Equipments.Clear();
            foreach (var item in lookup)
            {
                Equipments.Add(item);
            }
            EquipmentView = CollectionViewSource.GetDefaultView(Equipments);
            EquipmentView.Filter = new Predicate<object>(Filter);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message, "An error occurred", MessageBoxButton.OK, MessageBoxImage.Warning);
            //create new error object from the exception and add to DB
            Error error = new Error
            {
                ErrorMessage = e.Message,
                ErrorTimeStamp = DateTime.Now,
                ErrorStackTrace = e.StackTrace,
                LoginId = CurrentUser.LoginId
            };
            await _errorDataService.AddError(error);
        }
    }

EquipmentView.Filter调用Filter方法:

 public bool Filter(object obj)
    {
        var data = obj as EquipmentLookup;

        if (EquipmentView != null)
        {
            if (!string.IsNullOrEmpty(_filterString))
            {
                string allcaps = _filterString.ToUpper();
                return data.TypeName.StartsWith(_filterString) || data.TypeName.StartsWith(allcaps);
            }
            return true;
        }
        return false;
    }

仅当TypeName属性以filterstring开头时才返回true,filterstring是绑定到我的搜索栏的字符串。

现在我想到我只需要将datagrid ItemsSource设置为EquipmentView。如果我这样做,一切正常,数据网格只显示与搜索栏匹配的内容。

显然,如果我将datagrid上的itemsSource设置回设备,它仍然有效,包括搜索栏。为什么是这样?据我所知,我对EquipmentView的过滤不应该改变设备的任何内容,但无论如何它似乎都是这样做的。

一切都很好,我只是希望我知道为什么。

搜索栏的XAML代码:

<TextBox Name="SearchBar" Margin="10 10 10 10" Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}"/>

数据网格:

        <DataGrid MaxHeight="800"
            ItemsSource="{Binding Equipments}"
            SelectedItem="{Binding SelectedEquipment, Mode=TwoWay}"
            IsReadOnly="True"
            CanUserReorderColumns="False"
            SelectionMode="Single"
            ColumnWidth="*">
            <DataGrid.ItemContainerStyle>
                <Style TargetType="DataGridRow">
                    <EventSetter Event="MouseDoubleClick"
                     Handler="Row_DoubleClick" />
                </Style>
            </DataGrid.ItemContainerStyle>
        </DataGrid>
答案

从WPF文档:

所有集合都有一个默认的CollectionView。 WPF始终绑定到视图而不是集合。如果直接绑定到集合,WPF实际上绑定到该集合的默认视图。此默认视图由​​集合的所有绑定共享,这会导致对集合的所有直接绑定共享一个默认视图的排序,过滤器,组和当前项特征。

现在在您的代码中,您正在执行此操作:

EquipmentView = CollectionViewSource.GetDefaultView(Equipments);
EquipmentView.Filter = new Predicate<object>(Filter);

以上是关于使用WPF MVVM过滤datagrid,它可以工作,但我不知道为什么的主要内容,如果未能解决你的问题,请参考以下文章

使用 WPF MVVM 过滤数据网格,它可以工作,但我不知道为啥

如何使用 MVVM 自动隐藏 WPF 中的 DataGrid 列? [复制]

使用 MVVM 从 WPF 中的 TextBox 进行正确的 DataGrid 搜索

WPF MVVM 将 ComboBox 绑定到 Datagrid 选定项

具有多个图像的 WPF DataGrid RowDetailsTemplate (MVVM)

在 MVVM 中的 Datagrid 中绑定 WPF 组合框不保存更改