我有一个在模型类中定期更新的列表对象。我想使用计算属性将这些更改从我的模型传播到我的视图。
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经常更新,但列表对象本身永远不会被重新分配。
为什么会这样?有没有办法在不重建列表的情况下触发更新?
答案 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
维护/同步。