【问题标题】:ObservableCollection Collection Changed event not firingObservableCollection Collection Changed 事件未触发
【发布时间】:2015-04-15 21:37:32
【问题描述】:

我的 ViewModel 中有一个可观察的集合,绑定到数据网格。我想根据对集合的更改/对数据库的更新(使用 LINQ to SQL)实现一些逻辑来刷新其他窗口中的数据。

这是我的视图模型代码:

    public FTViewModel(int JobID)
    {
        _windowCloseAction = new DelegateCommand(OnWindowClose);
        _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID);
        _oFTrn.CollectionChanged += oFTrnCollectionChanged;
    }

    void oFTrnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (FilesTransmitted f in e.NewItems)
                f.PropertyChanged += FilesTransmitted_PropertyChanged;
        }
        if (e.OldItems != null)
        {
            foreach (FilesTransmitted f in e.OldItems)
                f.PropertyChanged -= FilesTransmitted_PropertyChanged;
        }
    }

    void FilesTransmitted_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "DocumentNumber")
        {
            _filesTransmittedChange = true;
        }
        _refreshViews = true;
    }

和 ObservableCollection 构造函数:

class ObservableFilesTransmitted : ViewableCollection<FilesTransmitted>
{
    public ObservableFilesTransmitted(DocControlDC dataDc, int ID)
    {
        foreach (FilesTransmitted ftran in dataDc.FilesTransmitteds.Where(x=>x.JobID==ID).OrderByDescending(x => x.TransmittalName))
        {
            this.Add(ftran);
        }
    }
}

调试器不会在 oFTrnCollectionChanged 中停止。我认为是因为创建可观察集合的调用发生在我添加 CollectionChanged 事件之前。但显然我不能切换这两条线。我已经查看了有关此的各种 StackOverflow 和 CodeProject 主题,似乎我所拥有的应该可以工作。我是否需要添加和删除一个虚拟项目才能调用 CollectionChanged 处理程序?我错过了什么?

似乎我应该有一个不添加任何成员的构造函数(用于可观察集合),以及一个从数据库添加成员的函数。然后我可以调用 new,添加 collectionchanged 处理程序,然后填充集合。我希望避免这种程度的重写,但也许这是唯一合理的方法。

【问题讨论】:

  • Observable 集合应该自动触发属性更改事件。

标签: c# wpf


【解决方案1】:

当我遇到这个问题时,最简单的解决方法就是在开始时手动订阅。

public FTViewModel(int JobID)
{
    _windowCloseAction = new DelegateCommand(OnWindowClose);
    _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID);
    foreach(var item in _oFTrn)
    {
        item.PropertyChanged += FilesTransmitted_PropertyChanged;
    }
    _oFTrn.CollectionChanged += oFTrnCollectionChanged;
}

然而,更好的解决方案是使用从BindingList&lt;T&gt; 派生的类,而不是使用派生自ObserveableCollection&lt;T&gt; 的类。任何引发其 PropertyChanged 事件的成员都将导致集合引发 ListChanged,更改类型为 ItemChanged

public FTViewModel(int JobID)
{
    _windowCloseAction = new DelegateCommand(OnWindowClose);
    _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID);
    _oFTrn.CollectionChanged += oFTrnListChanged;
}

void oFTrnListChanged(object sender, ListChangedEventArgs e)
{
    if (e.ListChangedType == ListChangedType.ItemChanged)
    {
        if (e.PropertyDescriptor.Name == "DocumentNumber")
        {
            _filesTransmittedChange = true;
        }
    }
    _refreshViews = true;
}

【讨论】:

  • 捂脸。当然,我不确定为什么我没有立即走这条路,尽管我在最初的修复后最终到达了那里(如下)。
【解决方案2】:

我只是更改了 ObservableCollection 构造函数并添加了一个填充函数:

新的视图模型代码:

    public FTViewModel(int JobID)
    {
        _oFTrn = new ObservableFilesTransmitted(_dataDc, JobID);
        _oFTrn.CollectionChanged += oFTrnCollectionChanged;
        _oFTrn.FillCollection();

    }

新的 ObservableCollection 类:

class ObservableFilesTransmitted : ViewableCollection<FilesTransmitted>
{
    DocControlDC _dc = null;
    int _jobID = 0;

    public ObservableFilesTransmitted(DocControlDC dataDc, int ID)
    {
        _dc = dataDc;
        _jobID = ID;
    }

    public void FillCollection()
    {
        foreach (FilesTransmitted ftran in _dc.FilesTransmitteds.Where(x=>x.JobID==_jobID).OrderByDescending(x => x.TransmittalName))
        {
            this.Add(ftran);
        }
    }
}

这一切都按预期工作。但它会为添加的每个项目调用。我可能会想到我只是循环遍历集合并为 viewmodel 构造函数中的每个项目添加 propertychanged 处理程序。似乎这样对性能的影响较小。

【讨论】:

    猜你喜欢
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多