首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ObservableCollection和项目PropertyChanged

ObservableCollection和项目PropertyChanged
EN

Stack Overflow用户
提问于 2009-05-23 16:57:17
回答 5查看 78.5K关注 0票数 57

我见过很多关于这个问题的讨论,但也许我只是个新手太难理解了。如果我有一个可观察的集合,它是"PersonNames“的集合,如msdn示例(http: //msdn.microsoft.com/en-us/library/ms748365.aspx)中的集合,如果添加或删除了PersonName,则会得到对视图的更新。我也希望在更改PersonName中的属性时得到对视图的更新。就像我换了名字一样。我可以为每个属性实现OnPropertyChanged,并让这个类从INotifyPropertyChanged派生出来,这似乎会像预期的那样被调用。

我的问题是,由于属性的更改不会导致ObservableCollection__发生任何事件,视图如何从ObservableCollection获取更新的数据?

这可能是真的很简单的事情,但为什么我似乎找不到一个例子令我惊讶。有人能帮我解释一下这一点吗?或者有任何关于例子的指点,我会非常感激的。在我们当前的WPF应用程序中,我们在多个地方都有这样的场景,并且正在努力解决这个问题。

“通常,负责显示数据的代码向屏幕上当前显示的每个对象添加一个PropertyChanged事件处理程序。”

谁能给我举个例子说明一下这意味着什么?我的视图绑定到我的ViewModel,它有一个ObservableCollection。此集合由一个RowViewModel组成,它具有支持PropertiesChanged事件的属性。但我不知道如何使集合本身更新,所以我的视图将被更新。

EN

回答 5

Stack Overflow用户

发布于 2010-08-13 15:54:24

下面是如何将/分离每个项的PropertyChanged事件。

代码语言:javascript
复制
ObservableCollection<INotifyPropertyChanged> items = new ObservableCollection<INotifyPropertyChanged>();
items.CollectionChanged += items_CollectionChanged;

static void items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.OldItems != null)
    {
        foreach (INotifyPropertyChanged item in e.OldItems)
            item.PropertyChanged -= item_PropertyChanged;
    }
    if (e.NewItems != null)
    {
        foreach (INotifyPropertyChanged item in e.NewItems)
            item.PropertyChanged += item_PropertyChanged;
    }
}

static void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    throw new NotImplementedException();
}
票数 76
EN

Stack Overflow用户

发布于 2013-11-12 20:58:07

我们在WPF-chat中写了这个:

代码语言:javascript
复制
public class OcPropertyChangedListener<T> : INotifyPropertyChanged where T : INotifyPropertyChanged
{
    private readonly ObservableCollection<T> _collection;
    private readonly string _propertyName;
    private readonly Dictionary<T, int> _items = new Dictionary<T, int>(new ObjectIdentityComparer());
    public OcPropertyChangedListener(ObservableCollection<T> collection, string propertyName = "")
    {
        _collection = collection;
        _propertyName = propertyName ?? "";
        AddRange(collection);
        CollectionChangedEventManager.AddHandler(collection, CollectionChanged);
    }

    private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                AddRange(e.NewItems.Cast<T>());
                break;
            case NotifyCollectionChangedAction.Remove:
                RemoveRange(e.OldItems.Cast<T>());
                break;
            case NotifyCollectionChangedAction.Replace:
                AddRange(e.NewItems.Cast<T>());
                RemoveRange(e.OldItems.Cast<T>());
                break;
            case NotifyCollectionChangedAction.Move:
                break;
            case NotifyCollectionChangedAction.Reset:
                Reset();
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }

    }

    private void AddRange(IEnumerable<T> newItems)
    {
        foreach (T item in newItems)
        {
            if (_items.ContainsKey(item))
            {
                _items[item]++;
            }
            else
            {
                _items.Add(item, 1);
                PropertyChangedEventManager.AddHandler(item, ChildPropertyChanged, _propertyName);
            }
        }
    }

    private void RemoveRange(IEnumerable<T> oldItems)
    {
        foreach (T item in oldItems)
        {
            _items[item]--;
            if (_items[item] == 0)
            {
                _items.Remove(item);
                PropertyChangedEventManager.RemoveHandler(item, ChildPropertyChanged, _propertyName);
            }
        }
    }

    private void Reset()
    {
        foreach (T item in _items.Keys.ToList())
        {
            PropertyChangedEventManager.RemoveHandler(item, ChildPropertyChanged, _propertyName);
            _items.Remove(item);
        }
        AddRange(_collection);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(sender, e);
    }

    private class ObjectIdentityComparer : IEqualityComparer<T>
    {
        public bool Equals(T x, T y)
        {
            return object.ReferenceEquals(x, y);
        }
        public int GetHashCode(T obj)
        {
            return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
        }
    }
}

public static class OcPropertyChangedListener
{
    public static OcPropertyChangedListener<T> Create<T>(ObservableCollection<T> collection, string propertyName = "") where T : INotifyPropertyChanged
    {
        return new OcPropertyChangedListener<T>(collection, propertyName);
    }
}
  • 弱事件
  • 跟踪将同一项多次添加到集合中。
  • 它使孩子们的财产发生了变化。
  • 静态类只是为了方便。

像这样使用它:

代码语言:javascript
复制
var listener = OcPropertyChangedListener.Create(yourCollection);
listener.PropertyChanged += (sender, args) => { //do you stuff}
票数 27
EN

Stack Overflow用户

发布于 2011-06-17 18:44:56

比尔,

我相信你已经找到了解决你的问题的办法,但是我把这个问题发布给了所有有共同问题的人。您可以用这个类来代替ObservableCollections,后者是实现INotifyPropertyChanged的对象的集合。这有点苛刻,因为它说列表需要重置,而不是找到一个已更改的属性/项,但是对于小列表,性能影响应该是不可见的。

Marc

代码语言:javascript
复制
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;

namespace WCIOPublishing.Helpers
{
    public class ObservableCollectionWithItemNotify<T> : ObservableCollection<T> where T: INotifyPropertyChanged 
    {

        public ObservableCollectionWithItemNotify()
        {
            this.CollectionChanged += items_CollectionChanged;
        }


        public ObservableCollectionWithItemNotify(IEnumerable<T> collection) :base( collection)
        {
            this.CollectionChanged += items_CollectionChanged;
            foreach (INotifyPropertyChanged item in collection)
                item.PropertyChanged += item_PropertyChanged;

        }

        private void items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if(e != null)
            {
                if(e.OldItems!=null)
                    foreach (INotifyPropertyChanged item in e.OldItems)
                        item.PropertyChanged -= item_PropertyChanged;

                if(e.NewItems!=null)
                    foreach (INotifyPropertyChanged item in e.NewItems)
                        item.PropertyChanged += item_PropertyChanged;
            }
        }

        private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var reset = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
            this.OnCollectionChanged(reset);

        }

    }
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/901921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档