RaisePropertyChanged不适用于集合

时间:2012-11-11 14:33:50

标签: c# windows-phone-7 binding mvvm-light

我正在使用mvvm-light,我注意到有关RaisePropertyChanged的这种奇怪行为。

XAML:

<ListBox ItemsSource="{Binding Collection}"/>
<TextBlock Text="{Binding Text}"/>

可观察的课程:

public class A : ObservableObject
{
    private string _b;
    public string B
    {
        get { return this._b; }
        set
        {
            this._b = value;
            this.RaisePropertyChanged("B");
        }
    }
}

VM:

public MainViewModel(IDataService dataService) { this.Collection = new List<A>(...); }

public RelayCommand Command1
{
    get
    {
        return this._command1 ?? (this._command1= new RelayCommand(() =>
        {
            this.Collection.Add(new A());
            this.Collection[2].B = "updated";
            this.RaisePropertyChanged("Collection");
            this.RaisePropertyChanged("Text");
        }));
    }
}

public RelayCommand Command2
{
    get { return this._command2?? (this._command2 = new RelayCommand(() => { this.Text++; })); }
}

public List<A> Collection { get; set; }
public int Text { get; set; }

因此,RaisePropertyChanged(“Collection”)不会在RaisePropertyChanged(“Text”)执行时更新绑定。我可以通过多次执行Command2和之后的Command1来看到它。如果Collection是一个ObservableCollection,则新元素显示在视图中,但更新的项不是,这意味着ObservableCollection的内部机制可以工作,但不是RaisePropertyChanged。

1 个答案:

答案 0 :(得分:4)

首先,对问题的解释:

在Windows Phone上,为依赖项属性设置值时,框架会在内部检查新值是否与旧值不同(可能是出于优化目的)。当您引发PropertyChanged事件或直接将集合重新分配给ItemsSource属性(它只是ItemsControl.ItemsSourceProperty依赖项属性的包装器)时,框架会检测到该值实际上没有不要更改并且不更新属性。因此,ListBox永远不会收到您的更改通知,也不会更新。

ObservableCollection有效,因为它使用了完全不同的机制:ListBox直接订阅了集合的CollectionChanged事件,因此不会受到依赖性限制的阻碍属性。


现在,如何解决这个限制?我能想到的唯一解决方法是:

  1. 使用ObservableCollection代替List
  2. null分配到ItemsSource的{​​{1}}媒体资源,然后重新分配您的收藏
  3. ListBox绑定到每次调用时都会返回不同集合的属性:

    ListBox