在NotifyPropertyChanged WPF之后,计算列表不会更新

时间:2018-02-27 00:06:38

标签: c# wpf

我有一个在模型类中定期更新的列表对象。我想使用计算属性将这些更改从我的模型传播到我的视图。

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private Zebra MyZebra { get; } = new Zebra();

    public IList<Stripe> StripeCollection => MyZebra.Stripes;

    public ViewModel()
    {
        MyZebra.StripesChanged += (sender, args) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StripeCollection"));
    }
}

我绑定到WPF对象的ItemsSource,如下所示:

ItemsSource="{Binding StripeCollection}"

当事件触发时,它不会更新我的绑定。当我在触发PropertyChanged事件之前输入断点时,我发现我的集合确实更新了我在模型和ViewModel中的所需方式。

如果我更改此行:

public IList<Stripe> StripeCollection => MyZebra.GetStripes;

为:

public IList<Stripe> StripeCollection => new List<Stripe>(MyZebra.GetStripes);

绑定确实更新。但是,每次条纹更改时,我都不想复制列表。 (显然Zebras经常更换条纹)。

MyZebras内部的List经常更新,但列表对象本身永远不会被重新分配。

为什么会这样?有没有办法在不重建列表的情况下触发更新?

1 个答案:

答案 0 :(得分:0)

问题在于,StripeCollection(对MyZebra.Stripes的引用)的值没有改变,因此尽管有PropertyChanged通知,但您看不到任何更改。
您已找到的一种可能的解决方案。

另一个避免生成新对象的方法是将StripeCollection handler StripesChanged临时设置为null。你可以这样做,你必须重写StripeCollection

public IList<Stripe> StripeCollection {
  get { return _stripeCollection; }
  set {
    _stripeCollection = value;
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StripeCollection)));
  }
} 
private IList<Stripe> _stripeCollection=MyZebra.Stripes;

MyZebra.StripesChanged += (sender, args) => {var tmpCol=StripeCollection; StripeCollection=null; StripeCollection=tmpCol;};

结果是您的UI控件将被刷新(整个列表)。

更好的解决方案是使用ObservableCollection,正如Jordy van Eijk所建议的那样。

更新

CollectionView还有一个解决方案:

public ICollectionView StripeCollection
{
    get { return _stripeCollection; }
    set
    {
        _stripeCollection = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StripeCollection)));
    }
}
private ICollectionView _stripeCollection =new CollectionView(MyZebra.Stripes);
MyZebra.StripesChanged += (sender, args) => {StripeCollection.Refresh();};

另一个解决方案是对StripeCollection使用ObservableCollection,并在处理程序中与MyZebra.Stripes维护/同步。