【问题标题】:Dependency Property and ViewModel initialization problem依赖属性和ViewModel初始化问题
【发布时间】:2010-01-26 22:28:31
【问题描述】:

我正在尝试添加自己的 ItemsSource 以向图表提供 GraphViewModel 列表。我认为我的做法不太正确,因为当我创建第一个 GraphViewModel 并将其添加到图表时,我的 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
}

【问题讨论】:

    标签: wpf mvvm dependency-properties


    【解决方案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
      }
    

    【讨论】:

    • 所以在我的虚拟机中,我有一个属性是 ObserverableCollection。我理解您所说的大部分内容,但是当我在 VM 初始化期间向集合添加新的 GraphViewModel 时,不会调用 OnGraphsCollectionChanged。仅在 VM 初始化后。你能提供一个我需要做些什么来修复的小例子吗?我对这一切都很陌生。谢谢!
    • 做了一些改动,看看
    猜你喜欢
    • 1970-01-01
    • 2021-10-09
    • 2012-07-25
    • 2017-11-29
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多