2

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

xml:

<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");
        }
    }
}

虚拟机:

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 无效。

4

1 回答 1

4

首先,对问题的解释:

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

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


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

  1. 使用 aObservableCollection而不是 aList
  2. 分配nullItemsSource您的财产ListBox,然后重新分配您的收藏
  3. 将绑定ListBox到每次调用时都会返回不同集合的属性:

    public List<A> CollectionCopy
    {
        get
        {
            return this.Collection.ToList();
        }
    }
    
于 2012-11-11T17:57:13.917 回答