有谁知道为什么这段代码不起作用:
public class CollectionViewModel : ViewModelBase {
public ObservableCollection<EntityViewModel> ContentList
{
get { return _contentList; }
set
{
_contentList = value;
RaisePropertyChanged("ContentList");
//I want to be notified here when something changes..?
//debugger doesn't stop here when IsRowChecked is toggled
}
}
}
public class EntityViewModel : ViewModelBase
{
private bool _isRowChecked;
public bool IsRowChecked
{
get { return _isRowChecked; }
set { _isRowChecked = value; RaisePropertyChanged("IsRowChecked"); }
}
}
ViewModelBase
包含 RaisePropertyChanged
等的所有内容,除了这个问题之外,它还可以用于其他所有内容 .
16 回答
当您更改集合中的值时,不会调用ContentList的Set方法,而是应该注意CollectionChanged事件触发 .
好的,今天两次我被MSDN文档弄错了 . 在我给你的链接中说:
但是当项目发生变化时,它实际上不会触发 . 我想你需要一个更强大的方法然后:
如果你需要这么多,你可能希望继承自己的
ObservableCollection
,当一个成员自动触发PropertyChanged
事件时触发CollectionChanged
事件(就像它在文档中所说的那样......)这是一个子类ObservableCollection的drop-in类,当列表项的属性发生更改时,实际上会引发Reset操作 . 它强制执行所有项目
INotifyPropertyChanged
.这样做的好处是,您可以将数据绑定到此类,并且所有绑定都将随着项属性的更改而更新 .
这使用了上述想法,但使其成为派生的“更敏感”的集合:
我把我希望的一个非常强大的解决方案放在一起,包括其他答案中的一些技巧 . 这是一个派生自
ObservableCollection<>
的新类,我称之为FullyObservableCollection<>
它具有以下功能:
它添加了一个新事件
ItemPropertyChanged
. 我故意把它与现有的_2374132分开:以帮助向后兼容 .
因此可以在随附的新
ItemPropertyChangedEventArgs
中给出更多相关细节:原始PropertyChangedEventArgs
和集合中的索引 .它从
ObservableCollection<>
复制所有构造函数 .它正确处理正在重置的列表(
ObservableCollection<>.Clear()
),避免可能的内存泄漏 .它覆盖基类的
OnCollectionChanged()
,而不是对CollectionChanged
事件的资源密集型订阅 .代码
完整的
.cs
文件如下 . 请注意,已经使用了C#6的一些功能,但是向后端移植它应该相当简单:NUnit测试
所以你可以检查你可能做出的改变(并看看我最初测试的是什么!),我还包括了我的NUnit测试类 . 显然, the following code is not necessary 只是在你的项目中使用
FullyObservableCollection<T>
.NB 测试类使用PRISM中的
BindableBase
来实现INotifyPropertyChanged
. 主代码不依赖于PRISM .ObservableCollection不会将单个项目更改传播为CollectionChanged事件 . 您需要订阅每个事件并手动转发,或者您可以查看BindingList[T]类,它将为您执行此操作 .
添加到TruelyObservableCollection事件“ItemPropertyChanged”:
我使用Jack Kenyons的答案来实现我自己的OC,但是我想指出我必须做出的一个改变才能让它发挥作用 . 代替:
我用过这个:
如果action是.Remove,似乎“e.NewItems”产生null .
只需在这个主题上加上我的2美分 . 感觉TrulyObservableCollection需要使用ObservableCollection找到的另外两个构造函数:
我知道我为这个派对来得太晚了,但也许 - 这会对某人有所帮助..
Here你可以找到我的ObservableCollectionEx实现 . 它有一些功能:
它支持ObservableCollection中的所有内容
它是线程安全的
它支持ItemPropertyChanged事件(每次触发Item.PropertyChanged项时都会引发)
它支持过滤器(因此,您可以创建ObservableCollectionEx,将另一个集合作为Source传递给它,使用简单谓词过滤 . 在WPF中非常有用,我在我的应用程序中使用了很多这个功能) . 更多 - 通过INotifyPropertyChanged界面过滤跟踪项目的更改 .
当然,任何评论都表示赞赏;)
如果我知道ObservableCollection只在我们添加/删除或移动我们的集合中的项目时才发生事件 . 当我们简单地更新集合项集合中的一些属性时,不要发出信号,并且不会更新UI .
你可以模拟在Model类中实现 INotifyPropertyChange . 而且当我们更新集合项目中的某些属性时,它会自动更新UI .
然后
在我的情况下,我使用ListView绑定此集合,并在ItemTemplate中设置Binding to Model属性,它工作正常 .
这是一些片段
Windows XAML :
Model code example:
And ViewModel implementation:
我使用的标准observablecollection的简单解决方案:
不要添加到您的 property 或直接更改它的内部项目,而是创建一些像这样的临时集合
并添加项目或对tmpList进行更改,
然后通过作业将它传递给你的实际 property .
这将改变整个属性,导致您根据需要注意INotifyPropertyChanged .
我尝试这个解决方案,但只有当我更改集合时,像RaisePropertyChange(“SourceGroupeGridView”)一样对我有效,为每个项目添加或更改触发 .
问题在于:
NotifyCollectionChangedAction.Reset此操作对groupsgrid中的所有项进行完全重新绑定,在RaisePropertyChanged中等效 . 当您使用它时,所有gridview组都会刷新 .
如果您只想在UI中刷新新项目的组,则不使用重置操作,您需要在itemproperty中模拟添加操作,如下所示:
抱歉,我的英文,并感谢基本代码:),我希望这有助于某人^ _ ^
Enjoi!
这是上述解决方案的扩展方法......
而不是ObservableCollection或TrulyObservableCollection,请考虑使用BindingList并调用ResetBindings方法 .
例如:
给定一个事件,例如点击,您的代码将如下所示:
我的模型看起来像这样:
这是我的实现版本 . 如果列表中的对象没有实现INotifyPropertyChanged,它会检查并抛出错误,因此在开发时不能忘记该问题 . 在外部,您使用ListItemChanged事件确定列表或列表项本身是否已更改 .
2行代码的简单解决方案 . 只需使用复制构造函数 . 无需编写TrulyObservableCollection等 .
例:
没有复制构造函数的另一种方法您可以使用序列化 .