当从数据绑定更新时,是否可以将筛选器自动应用于集合?

本文关键字:筛选 应用于 集合 更新 数据绑定 是否 | 更新日期: 2023-09-27 18:15:00

这个问题的简短版本是:我是否需要手动刷新视图,以便将过滤器应用于具有数据绑定的集合,或者它可以作为正常数据绑定过程的一部分完成?

我有一个DataGrid,我试图自动保持最新。我想做的一件事是排除具有特定值设置为true的项目。这是我用来实现这一点的代码。这是从不同的地方拼凑起来的,但它应该能让你明白。这可能看起来像一个相当大的代码墙,但我已经尽量保持片段尽可能小,同时保持我的意图可辨。

这是设置我应用于集合的过滤器的代码:

CollectionView processView = (CollectionView)CollectionViewSource.GetDefaultView(ProcessBox.ItemsSource);
processView.Filter = ProcessFilter;
// Elsewhere
        private bool ProcessFilter(object item)
        {
            ProcessContainer thisItem = item as ProcessContainer;
            if (thisItem.IsScheduled == true)
                return false;
            if (String.IsNullOrEmpty(FilterInput.Text))
            {
                return true;
            }
            else
            {
                return (thisItem.ProcessName.IndexOf(FilterInput.Text, StringComparison.OrdinalIgnoreCase) >= 0);
            }
        }

下面我有一个允许用户按文本过滤列表的输入。这个可以工作,但是它需要手动更新。

    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        CollectionViewSource.GetDefaultView(ProcessBox.ItemsSource).Refresh();
    }

下面是数据网格的示例:

    <DataGrid x:Name="ProcessBox" SelectionMode="Extended" ScrollViewer.HorizontalScrollBarVisibility="Hidden" GridLinesVisibility="None" AutoGenerateColumns="False" IsReadOnly="True" Margin="0,0,0,33" CanUserReorderColumns="False" MinColumnWidth="50" CanUserResizeRows="False">
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsScheduled}" Value="true">
                        <Setter Property="Foreground" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Process" Binding="{Binding ProcessName}" />
            <DataGridTextColumn Header="Memory" Binding="{Binding Memory}" />
        </DataGrid.Columns>
    </DataGrid>

我有红色文本触发器来确保它被正确地绑定和设置。我的模型实现了INotifyPropertyChanged,当布尔值改变时,列表上的颜色将自动更新颜色。也就是说,当我设置布尔值时,会运行:

    public bool IsScheduled
    {
        get { return isScheduled; }
        set { isScheduled = value; NotifyPropertyChanged(); }
    }

…颜色如预期的那样改变,但是过滤器没有运行。

总结一下…

我用自己的代码过滤ObservableCollection<T>,当我手动更新它时它可以工作。我的模型实现了INotifyPropertyChanged接口,xaml中的数据触发器获取更改,当添加或删除项目时,集合本身会按预期更新。但是,如果我尝试启用在过滤器中触发排除的布尔值,它将不会被隐藏,直到在视图上调用手动Refresh()

是否有办法使其自动更新或过滤器需要应用手动刷新?

当从数据绑定更新时,是否可以将筛选器自动应用于集合?

由于您正在使用MVVM,我建议将设置过滤器的代码移动到ViewModel中,如果IsScheduled属性也暴露在ViewModel上,那么它将很容易触发过滤器的刷新,可能是这样的:

public class ExampleViewModel : BaseViewModel
{
    private readonly ObservableCollection<ExampleChildViewModel> _items;
    private readonly ListCollectionView _filteredItems;
    public ExampleViewModel()
    {
        _items = new RadObservableCollection<ExampleChildViewModel>();
        _filteredItems = new ListCollectionView(_items) {Filter = MyFilter};
        // todo - fill the items...
    }
    public IEnumerable Items { get { return _filteredItems; } }
    public bool IsScheduled
    {
        get { return isScheduled; }
        set
        {
            isScheduled = value;
            NotifyPropertyChanged();
            _filteredItems.Refresh();
        }
    }
    private bool MyFilter(object item)
    {
        ExampleChildViewModel thisItem = item as ExampleChildViewModel;
        if (thisItem == null)
        {
            return false;
        }
        if (thisItem.Name == "AwkwardCoder")
        {
            return true;
        }
        return false;
    }
}