首页 > 解决方案 > ListCollectionView 使用 MVVM 模型过滤 DataGrid

问题描述

我目前正在尝试将 ListCollectionView 过滤器应用于 WPF DataGrid。它应该适用于我的 MVVM。

问题是,过滤器函数仅在应用程序启动时调用,而不是在 TextBox 更新后(即过滤器)。

数据网格 XAML:

<DataGrid x:Name="DbGrid"
                    ItemsSource="{Binding DbInterruptions}" AutoGenerateColumns="False"
                          HorizontalAlignment="Left" Height="314" Margin="2,50,0,0" VerticalAlignment="Top" Width="1024" Grid.ColumnSpan="5" Grid.RowSpan="3" Grid.Row="1" Grid.Column="1">
     <DataGrid.Columns>
                 <DataGridTextColumn Header="Timestamp" Binding="{Binding TimeLocal, StringFormat='{}{0:HH:mm:ss.fff}'}"/>
                 <DataGridTextColumn Header="Date" Binding="{Binding TimeLocal, StringFormat='{}{0:dd.MM.yyyy}'}"/>
                 <DataGridTextColumn Header="(Interrupted) Phase" Binding="{Binding Payload.InterruptedPhase}"/>
                 <DataGridTextColumn Header="Event" Binding="{Binding Payload.Event}"/>
                 <DataGridTextColumn Header="Method" Binding="{Binding Payload.Method}"/>
                 <DataGridTextColumn Header="Cutter Id" Binding="{Binding CutterId}"/>
                 <DataGridTextColumn Header="Job" Binding="{Binding Payload.Job}"/>
                 <DataGridTextColumn Header="Event type" Binding="{Binding EventType}"/>
                 <DataGridTextColumn Header="Condition/Beam" Binding="{Binding Payload.Condition}"/>
     </DataGrid.Columns>
</DataGrid>

视图模型:

公共类 MainViewModel : ViewModelBase { public ObservableCollection DbInterruptions => new ObservableCollection(_mqttModel.JobPhaseHistory);

    public MainViewModel()
    {
        ReloadFromDatabaseButtonClick();
        _mqttModel.JobHistoryChanged += () => RaisePropertyChanged(nameof(DbInterruptions));

        var filteredDbInterruptions = (ListCollectionView)CollectionViewSource.GetDefaultView(DbInterruptions);
        filteredDbInterruptions.Filter = UserFilter;
    }

    public ICommand ReloadFromDatabase => new RelayCommand(ReloadFromDatabaseButtonClick);

    private void ReloadFromDatabaseButtonClick()
    {
        _mqttModel.RefreshHistoricData();
    }

    private string _jobNameFilter;
    public string JobNameFilter
    {
        get => _jobNameFilter;
        set
        {
            if (_jobNameFilter == value)
                return;
            
            _jobNameFilter = value;
            RaisePropertyChanged(nameof(JobNameFilter));

            if (!string.IsNullOrEmpty(TimeFilter))
                TimeFilter = "";
            if (!string.IsNullOrEmpty(EventNameFilter))
                EventNameFilter = "";

            var filteredDbInterruptions = (ListCollectionView)CollectionViewSource.GetDefaultView(DbInterruptions);
            filteredDbInterruptions.Refresh();
        }
    }

    private string _timeFilter;
    public string TimeFilter
    {
        get => _timeFilter;
        set
        {
            if (_timeFilter == value)
                return;

            _timeFilter = value;
            RaisePropertyChanged(nameof(TimeFilter));

            if (!string.IsNullOrEmpty(JobNameFilter))
                JobNameFilter = "";
            if (!string.IsNullOrEmpty(EventNameFilter))
                EventNameFilter = "";

            var filteredDbInterruptions = (ListCollectionView)CollectionViewSource.GetDefaultView(DbInterruptions);
            filteredDbInterruptions.Refresh();
        }
    }

    private string _eventNameFilter;
    public string EventNameFilter
    {
        get => _eventNameFilter;
        set
        {
            if (_eventNameFilter == value)
                return;
            
            _eventNameFilter = value;
            RaisePropertyChanged(nameof(EventNameFilter));

            if (!string.IsNullOrEmpty(TimeFilter))
                TimeFilter = "";
            if (!string.IsNullOrEmpty(JobNameFilter))
                JobNameFilter = "";

            var filteredDbInterruptions = (ListCollectionView)CollectionViewSource.GetDefaultView(DbInterruptions);
            filteredDbInterruptions.Refresh();
        }
    }


    private bool UserFilter(object item)
    {
        if(string.IsNullOrEmpty(JobNameFilter) && string.IsNullOrEmpty(TimeFilter) && string.IsNullOrEmpty(EventNameFilter))
        {
            return true;
        }

        var interruption = (item as Interruption);
        if (interruption != null)
        {
            if (!string.IsNullOrEmpty(JobNameFilter))
            {
                return interruption.Payload.Job.Contains(JobNameFilter);
            }

            if(!string.IsNullOrEmpty(TimeFilter))
            {
                //return interruption.TimeLocal.Equals()
                return true;
            }

            return interruption.Payload.Event.Contains(EventNameFilter);
        }

        return false;
    }

}

因此过滤器属性(名称、事件、时间)是连接到文本框的属性。如果没有必要,我不想通过代码隐藏来做到这一点。

有谁知道,我做错了什么?

标签: wpf.net-coredata-bindingdatagrid

解决方案


有谁知道,我做错了什么?

ObservableCollection每次调用时,您的属性都会创建一个新属性:

public ObservableCollection DbInterruptions => new ObservableCollection(_mqttModel.JobPhaseHistory);

你应该设置一次

public ObservableCollection DbInterruptions { get; } = new ObservableCollection(_mqttModel.JobPhaseHistory);

推荐阅读