Singleton OnPropertyChanged Not Firing

本文关键字:Firing Not OnPropertyChanged Singleton | 更新日期: 2023-09-27 18:16:14

我有一个名为DataModel的类,我在其中存储项目的ObservableCollection。我使用的是一个静态的ObservableCollection,但因为我想绑定到它,和OnPropertyChanged似乎不能正确地为静态属性工作,我创建了它作为一个单例:

public sealed class DataModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private static readonly DataModel instance = new DataModel();
    private DataModel() { }
    public static DataModel Instance
    {
        get
        {
            return instance;
        }
    }
    #region Projects
    private ObservableCollection<Project> projects = new ObservableCollection<Project>();
    public ObservableCollection<Project> Projects
    {
        get
        {
            return projects;
        }
        set
        {
            if (projects == value)
            {
                return;
            }
            projects = value;
            OnPropertyChanged("Projects");
        }
    }
    #endregion Projects
    public void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

当我点击一个按钮时,

Project newProject = new Project() { Title = "Test" };
DataModel.Instance.Projects.Add(newProject);

根据我从各种来源得到的信息,这应该是正确的。然而,OnPropertyChanged事件永远不会被调用。如果我做

DataModel.Instance.Projects = new ObservableCollection<Project>();

被调用。但是将Project添加到集合中不会调用它

Singleton OnPropertyChanged Not Firing

OnPropertyChanged仅在重新分配该属性时自动触发。这就是为什么重新分配整个集合会导致它被触发的原因。修改集合会触发集合自己的CollectionChanged事件,因为你实际上并没有改变Projects引用,只是改变了它所引用的同一个集合。

如果你的集合被正确地绑定到控件的ItemsSource属性,例如

<ListView ItemsSource="{Binding Projects}"/>

如果数据上下文是您的DataModel实例,则除了添加新项之外不需要做任何事情。

如果您需要在集合更改时做一些事情,请订阅它的CollectionChanged事件:

private DataModel()
{
    Projects.CollectionChanged += Projects_CollectionChanged;
}
private void Projects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        // An item was added...
    }
}

我希望它不能工作。因为您正在向观察集合添加项,在这种情况下没有理由调用setter,因此OnPropertyChanged。这就是它在初始化DataModel.Instance时工作的原因。项目从调用代码。您可以显式地调用属性更改,如下所示:

Project newProject = new Project() { Title = "Test" };
DataModel.Instance.Projects.Add(newProject);
DataModel.Instance.OnPropertyChanged("Projects");

免责声明:虽然这是可能的,但您真的不需要这样做。这就是为什么他们为我们提供了ObservableCollection。任何添加或从该集合中删除的项目都将自动通知给视图。如果这不是真的,为什么有人会使用ObservableCollection而不是简单的List来进行数据绑定呢?