依赖属性和ViewModel初始化问题

时间:2010-01-26 22:28:32

标签: wpf mvvm dependency-properties

我正在尝试添加自己的ItemsSource以向图表提供GraphViewModel列表。我不认为我有这么正确,因为当我创建我的第一个GraphViewModel并将其添加到Graphs时,我的DP已更新,但OnGraphsCollectionChanged未被调用。

这应该如何运作?如果我通过绑定命令的按钮将图形添加到我的VM属性,那么一切都很好。

这是DP代码,任何人都可以解释这应该如何工作或者在初始化期间显示我的数据我做错了什么?

public static readonly DependencyProperty GraphsProperty = 
    DependencyProperty.Register("ItemsSource", 
    typeof(ObservableCollection<GraphViewModel>), 
    typeof(DynamicPlotter), 
    new FrameworkPropertyMetadata(new PropertyChangedCallback(ChangeGraphs)));

public ObservableCollection<GraphViewModel> ItemsSource
{
    get { return (ObservableCollection<GraphViewModel>)GetValue(GraphsProperty); }
    set
    {
        SetValue(GraphsProperty, value);
        ItemsSource.CollectionChanged += new NotifyCollectionChangedEventHandler(OnGraphsCollectionChanged);
    }
}

public static void ChangeGraphs(DependencyObject source, DependencyPropertyChangedEventArgs eventArgs)
{
    (source as   DynamicPlotter).UpdateGraphs((ObservableCollection<GraphViewModel>)eventArgs.NewValue);
}

private void UpdateLineGraphs(ObservableCollection<GraphViewModel> grphs)
{
    this.ItemsSource = grphs;
}

private void OnGraphsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // This never gets called when you set the ItemsSource, but is where all the work is done
}

1 个答案:

答案 0 :(得分:1)

只有在集合发生变化时才会调用CollectionChanged,如果在设置之前已经填充了集合,那么在添加/删除某些内容之前,您将永远不会收到通知。

其次,如果从xaml设置依赖项属性,则不使用getter / setter,依赖机制使用其自己的内部setter例程。您应该在ChangeGraphs属性回调函数中附加collectionChanged事件,因为只要设置/更改了属性,就会调用它。您可以使用它来取消挂起旧的collectionChanged事件,事件参数将为您提供旧的和新的值。

但实际上,它是一个可观察的集合,您不应该知道集合何时更改,因为您应该绑定到集合,当它更改时绑定机制将更新您的UI。

我会将我的代码更改为

  public ObservableCollection<GraphViewModel> ItemsSource {
     get { return (ObservableCollection<GraphViewModel>)GetValue(ItemsSourceProperty); }
     set { SetValue(ItemsSourceProperty, value); }
  }

  // Using a DependencyProperty as the backing store for ItemsSource.  This enables animation, styling, binding, etc...
  public static readonly DependencyProperty ItemsSourceProperty =
      DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<GraphViewModel>), typeof(DynamicPlotter), new UIPropertyMetadata(null, (o, e) => { ((DynamicPlotter)o).ItemsSourceChanged(); }));

  private void ItemsSourceChanged() {
     if (this.ItemsSource != null){
        //attach the collection changed listener, this will listen to all FUTURE collection changes, items that are added and removed
        this.ItemsSource.CollectionChanged +=new NotifyCollectionChangedEventHandler(ItemsSource_CollectionChanged);
        //do some inital processing with the items that are in the collection already when it is set
        this.UpdateGraphs(this.ItemsSource);
  }

  private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e){
          //this will get called if an item gets added or removed from the collection
  }