ObservableCollection Collection更改事件未触发

时间:2015-04-15 21:37:32

标签: c# wpf

我的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的错误?我错过了什么?

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

2 个答案:

答案 0 :(得分: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<T>派生的类,而不是使用从ObserveableCollection<T>派生的类。任何提升其PropertyChanged事件的成员都会导致该集合以ItemChanged

的更改类型引发ListChanged
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;
}

答案 1 :(得分:0)

我只是更改了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处理程序。看起来似乎不那么受到影响。