【问题标题】:Filter Method of ICollectionView and Properly Binding and ObservableCollection in MVVMMVVM中ICollectionView的过滤方法和正确绑定和ObservableCollection
【发布时间】:2017-07-25 01:14:05
【问题描述】:

我在 WPF 中遇到了 MVVM,我设置了一个 ObservableCollection 和一个 ICollectionViewICollectionView 设置为DataGrid 的ItemsSource,模型为Job 类型。

我已经为这两个集合设置了 getter 和 setter,但是当我在 ICollectionView 上设置 Filter 而不是 JobSearchString 过滤时,它们只是一遍又一遍地复制再次让我相信他们设置收藏夹的方式是完全错误的。

以下是两个集合的获取/设置方式:

public ObservableCollection<Job> AllJobs
{
    get
    {
        foreach (var job in _allJobsList)
            _allJobs.Add(job);
        return _allJobs;
    }
    set
    {
        if (_allJobs == value) return;
        OnPropertyChanged("AllJobs");
    }
}

public ICollectionView AllJobsView
{
    get
    {
        _allJobsView = CollectionViewSource.GetDefaultView(AllJobs);
        return _allJobsView;
    }
    set
    {
        if (_allJobsView == value)
        {
            return;
        }

        _allJobsView = value;
        OnPropertyChanged("AllJobsView");
    }
}

现在我有一个名为SearchString 的字符串绑定到TextBox.Text。当文本更改时,我会执行以下操作:

public string SearchString
{
    get => _searchString;
    set
    {
        if (_searchString == value) return;
        _searchString = value;
        FilterJobs();
        OnPropertyChanged("SearchString");
    }
}

private void FilterJobs()
{
    AllJobsView.Filter = x =>
    {
        var viewJob = x as Job;
        return viewJob != null && viewJob.Number.Contains(_searchString);
    };
}

现在当页面首次加载时,DataGrid 中加载了正确的 Jobs。但是,如果Job.Number 确实包含SearchString,则一旦用户键入Jobs,就会重复。如何设置集合以便我可以适当地设置过滤器?

【问题讨论】:

标签: c# wpf mvvm datagrid


【解决方案1】:

问题出在 ObservableCollection 的 getter 中。每次“获取”集合时,您都在重新将每个项目添加到集合中。

您的代码:

get
{
    foreach (var job in _allJobsList)
        _allJobs.Add(job);
    return _allJobs;
}

相反,它应该是:

get
{        
    return _allJobs;
}

您的 ObservableCollection 的设置器也缺少“设置器”(私有字段 = 值)代码:

set
{
    if (value != _allJobs)
    {
        _allJobs = value;
        OnPropertyChanged("AllJobs");
    }
}

您的财产 AllJobs 将是:

private ObservableCollection<Job> _allJobs;
public ObservableCollection<Job> AllJobs
{
    get
    {        
        return _allJobs;
    }
    set
    {
        if (value != _allJobs)
        {
            _allJobs = value;
            OnPropertyChanged("AllJobs");
        }
    }
}

集合的初始化应该在其他地方(而不是在属性的 getter 中),例如在 ViewModel 的构造函数中或/和在用户请求刷新集合后命令调用的方法中.

例如,如果您的 VieModel 被称为 MyViewModel 而您的 List&lt;Job&gt; 被称为 _allJobsList,您可以像这样初始化您的集合:

public MyViewModel()
{
    //fill the _allJobsList first, getting from a database for example: _allJobsList = GetJobs();
    //and then create an observable collection from that list
    AllJobs = new ObservableCollection<Job>(_allJobsList);
}

【讨论】:

    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多