我有ObservableCollection _cableList
个包含CableViewModel
类型的对象。 CableViewModel
对象具有布尔属性IsInDB
,如果另一个属性Type
列在另一个集合中,则应设置该属性。我收听PropertyChanged
事件以更新IsInDB
属性。这按预期工作,但我还需要更新添加到集合中的项目的IsInDB
属性。我尝试使用以下代码解决此问题:
public MainViewModel()
{
_cableList = new ObservableCollection<CableViewModel>();
_cableList.CollectionChanged += _cableListChanged;
}
private void _cableListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.OldItems != null)
{
foreach (INotifyPropertyChanged item in e.OldItems)
item.PropertyChanged -= cablePropertyChanged;
}
if(e.NewItems != null)
{
foreach (INotifyPropertyChanged item in e.NewItems)
{
item.PropertyChanged += cablePropertyChanged;
// This causes an exception
MessageBox.Show("Collection changed - new Item");
var x = (CableViewModel)item;
x.IsInDB = IsInCableDB(x.Type);
}
}
}
代码导致System.InvalidOperationException
表示“An ItemsControl
与其对象源不一致”,或者至少是我尝试翻译瑞典语错误消息。
我的代码出了什么问题?还有另一种解决方法吗?
编辑
我没有在原帖中显示完整的代码,因为我认为它与异常无关。但是我错了。
在我的原始帖子中,我没有显示或提及我出于调试目的而显示MessageBox
。每次将新对象添加到集合时都会显示。现在编辑上面的代码,以便包含MessageBox.Show
行。在此处发布原始邮件后,我从代码中删除了MessageBox
,结果异常消失了。 MessageBox
导致UI与集合不同步吗? (ObservableCollection
绑定到DataGrid
)
答案 0 :(得分:0)
在这种情况下,我建议使用ReactiveList并使用observables代替事件 - 这会使许多线程问题消失。
从好的方面来说,你可以这样做:
_cableList.ItemChanged.Where(x => x.PropertyName == "Cable").Select(x => x.Sender).Subscribe(x => {
//do something with the object
});
_cableList.ItemsAdded.Subscribe(x => x.IsInDB = IsInCableDB(x.Type);
答案 1 :(得分:0)
CollectionChanged
时都会显示一个消息框。当我删除消息框时,异常消失了。消息框是否导致UI与数据不同步?