我有一个ObservableCollection组件,一个带有另一个ObservableCollection的类,一个字符串和一个ComponentVersion。已通过我的视图正确更新了SelectedComponentVersion,但无法获取Components属性来触发它的setter / OnPropertyChanged。
private ObservableCollection<Component> components
public ObservableCollection<Component> Components
{
get { return foo; }
set { foo = value; OnPropertyChanged(); }
}
这是Component的类。
public class Component : ViewModelBase
{
private string componentName;
private ObservableCollection<ComponentVersion> componentVersions;
private ComponentVersion selectedComponent;
public string ComponentName
{
get { return componentName; }
set { componentName = value; OnPropertyChanged(); }
}
public ObservableCollection<ComponentVersion> ComponentVersions
{
get { return componentVersions; }
set { componentVersions = value; OnPropertyChanged(); }
}
public ComponentVersion SelectedComponent
{
get { return selectedComponent; }
set { selectedComponent = value; OnPropertyChanged(); }
}
public Component(string componentName, List<ComponentVersion> componentVersion)
{
ComponentName = componentName;
ComponentVersions = componentVersion.ToObservableCollection();
}
}
然后,我将从列表视图绑定到Component内部的SelectedComponent属性。
我已经阅读了无数有关设置CollectionChanged的堆栈溢出信息,并且尝试实现它没有运气。
Components.CollectionChanged += stuff;
private void stuff(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
throw new System.NotImplementedException();
}
但是从没有用断点测试过。
我完全错过了什么,失去了理智或愚蠢!如果有任何意义,请有人指出正确的方向。
P.S我的另一种解决方案是在列表视图中放置一个不可见的按钮,并发送命令告诉vm所选项目已更新。
答案 0 :(得分:5)
在这种情况下,当我想要在集合中某个项目的属性发生变化时做某事,我通常会在PropertyChanged
事件中关联一个CollectionChanged
事件
这是一个代码示例:
public MyViewModel()
{
// Setup Collection, with a CollectionChanged event
Components = new ObservableCollection<Component>();
Components.CollectionChanged += Components_CollectionChanged;
}
// In the CollectionChanged event (items getting added or removed from collection),
// hook up the PropertyChanged event
void Components_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach(MyType item in e.NewItems)
item.PropertyChanged += Component_PropertyChanged;
if (e.OldItems != null)
foreach(MyType item in e.OldItems)
item.PropertyChanged -= Component_PropertyChanged;
}
// In the PropertyChanged event, run some code if SelectedComponent property changed
void Component_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedComponent")
DoWork();
}
请注意,我们在这里使用两个单独的事件。
CollectionChanged
事件。这意味着将其设置为新集合,或者从集合中添加或删除项目。
这将捕获新添加的项目并连接PropertyChanged 处理程序,或为要删除的项目分离PropertyChanged处理程序 从集合中删除。
PropertyChanged
事件在属性更改并触发该事件时运行。当集合中任何项目的SelectedComponent
属性更改时,您将使用此事件运行代码答案 1 :(得分:2)
嗯,components
并没有改变。我不确定您是否正确设置了处理程序,但即使您设置正确,也只会触发CollectionChanged事件,如果集合发生了更改(添加或删除了项目)。
让我们说您有一些汽车,而且都是红色的。
您选择一辆汽车并将其颜色设置为蓝色。
收藏集没有更改。还是一样的车。没有汽车失踪,没有添加汽车。
您可能希望将自己附加到所有汽车的处理程序上,而不是集合的处理程序上。
所以总结一下:
ObservableCollection
属性更改的通知不会收到有关
是真的,这是设计使然。
答案 2 :(得分:2)
将项目添加到集合中时,您要“关联”这些项目感兴趣的事件,然后可以根据需要执行操作。如上所述,集合并没有改变,而是单个项目正在改变。
您可以做的一件事是扩展ObservableCollection类并覆盖功能,以便在更改集合时添加或删除项目,然后遍历集合中的项目并“关联”事件“有兴趣。要注意的一件事是,您可能必须遍历该集合并删除事件处理程序,然后再次对其进行“挂钩”,以停止为列表中的项目设置多个事件处理程序。
答案 3 :(得分:1)
ObservableCollection<T>
不会发送有关元素属性更改的通知。但是,System.ComponentModel
命名空间包含另一个集合,该集合支持该集合:您可以考虑改用BindingList<T>
,WPF也支持该集合(元素必须实现INotifyPropertyChanged
)。
请注意,尽管BindingList<T>
的伸缩性很差,并且其性能开始下降到成千上万个元素,因为它总是顺序地搜索更改的元素,以便在其ListChanged
事件中返回元素索引