无法通知ObservableCollection <t> <t>

时间:2018-10-24 16:17:32

标签: c# wpf events mvvm

我有一个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所选项目已更新。

4 个答案:

答案 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事件中返回元素索引