【问题标题】:Watch an object graph for changes观察对象图的变化
【发布时间】:2009-07-06 07:42:58
【问题描述】:

有没有办法观察对象图上任何对象的变化,并根据该变化做一些事情?

假设我有以下内容:

public class Main:INotifyPropertyChanged
{
    public ObservableCollection<Foo> FooItems { get; }
    public ObservableCollection<Bar> BarItems { get; }
}

public class Foo:INotifyPropertyChanged

public class Bar:INotifyPropertyChanged
{
    public ObservableCollection<Other> OtherItems { get; }
}

public class Other:INotifyPropertyChanged

在所有对象中实现某种更改通知系统的最佳方式是什么?例如自动保存,任何更改都会触发系统序列化Main 类。

我是否应该在 Main 类中使用胶水代码来观察 BarItems 的变化,连接到他们的 PropertyChanged?这似乎有点混乱,而且对我来说很容易出错。有没有更好的办法?

【问题讨论】:

    标签: c# .net design-patterns inotifypropertychanged


    【解决方案1】:

    与其引发他们自己的属性更改事件的对象,也许他们可以引发一个共享事件。例如:

    public class SharedChangeNotifier
    {
        public static event EventHandler<DataChangedEventArgs> SharedChangeEvent;
    
        protected void RaiseChangeEvent()
        {
            if (SharedChangeNotifier.SharedChangeEvent != null)
            {
                SharedChangeNotifier.SharedChangeEvent(
                    this, new DataChangedEventArgs());
            }
        }
    }
    
    public class Foo : SharedChangeNotifier
    {
        public int MyProperty
        {
            get { ... }
            set
            {
                ...
                RaiseChangeEvent();
            }
        }
    }
    

    然后,您可以将事件处理程序附加到静态 SharedChangeNotifier 的 SharedChangeEvent,以便在派生自 SharedChangeNotifier 的任何对象发生更改时收到通知,如下所示:

    SharedChangeNotifier.SharedChangeEvent += (sender, args) => {
        DoWhatever();
    };
    

    【讨论】:

    • 我可以做到这一点,但我也在使用 INotifyPropertyChanged 接口进行数据绑定,所以最好使用已有的接口。不过我会记住这一点。
    【解决方案2】:

    我刚刚在http://www.lennybacon.com/ReBlinderFleckChangeTracking.aspx阅读了一篇关于该问题的有趣博文

    帖子是德文的,但由于大部分是代码,应该没问题。

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      我过去的做法是创建一个单独的 ChangeTracker 类,其中包含一个将对象注册到其中的方法。在该方法中,使用反射来探索已注册的对象,并挂钩到其实现 INotifyPropertyChanged 的​​每个属性上的事件。

      然后您可以向 ChangeTracker 添加方法来询问状态,例如IsDirty(),甚至在 ChangeTracker 上实现 INotifyPropertyChanged。

      (请务必在 ChangeTracker 上实现和使用 IDisposable,并在那时删除所有事件处理程序)。

      【讨论】:

        【解决方案4】:

        您可以为所有实现 INotifyPropertyChanged 事件的项目使用相同的处理程序:

        foreach (INotifyPropertyChanged obj in FooItems)
            obj.PropertyChanged+= this.modified;
        
        // likewise for bar items, and when items are added
        
        private void modified(object sender, EventArgs args)
        {
            this.Save();
        }
        

        edit> 在添加项目时执行相同操作:

        private void addToList<T>(ref List<T> l, T item) where T : INotifyPropertyChanged
        {
            item.PropertyChanged += this.modified;
            l.Add(item);
        }
        

        调用它:

        Foo item = new Foo();
        List<Foo> fooItems = new List<Foo>();
        
        addToList<Foo>(ref fooItems, item);
        

        【讨论】:

        • 在 FooItems 中添加或删除项目时会怎样?
        猜你喜欢
        • 2017-09-07
        • 2018-07-12
        • 2021-01-12
        • 1970-01-01
        • 2015-12-17
        • 2018-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多