改变方法不叫上IList的依赖属性

问题描述:

我有,我有一个IList的依赖属性改变方法不叫上IList的依赖属性

public IList SelectedItems 
    { 
     get { return (IList)GetValue(SelectedItemsProperty); } 
     set { SetValue(SelectedItemsProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedItemsProperty = 
     DependencyProperty.Register("SelectedItems", typeof(IList), 
      typeof(MyCustomControl), new FrameworkPropertyMetadata(OnChangeSelectedItems) 
      { 
       BindsTwoWayByDefault = true 
      }); 

    private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var usercontrol = d as MyCustomControl; 
     var selected = e.NewValue as IList; 

     if (selected != null && selected.Count > 1) 
     { 

       //do something 
        usercontrol.label1.Content= selected[0]; 
     }    

    } 

这种依赖属性绑定到视图模型可观察集合的自定义控件,我的问题是,如果我加入一些在ViewModel OnChangeSelectedItems的构造函数中的视图模型可观察集合被调用,但如果我在可观察集合中的运行时添加更多项目,OnChangeSelectedItems不会被调用。我在这里丢失了什么。

编辑:工作液

private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var uc = d as UserControl1; 

     if (uc != null) 
     { 
      var oldObservable = e.OldValue as INotifyCollectionChanged; 
      var newObservable = e.NewValue as INotifyCollectionChanged; 
      if (oldObservable != null) 
      { 
       oldObservable.CollectionChanged -= uc.SelectedItemsContentChanged; 
      } 
      if (newObservable != null) 
      { 
       newObservable.CollectionChanged += uc.SelectedItemsContentChanged; 


      } 
     } 
    } 

    private void SelectedItemsContentChanged(object d, NotifyCollectionChangedEventArgs e) 
    { 
     //do something 
    } 
+0

@Clemens虽然它肯定是重复的,但我认为这个链接的Q/A没有一个好的标题以便作为参考。 – grek40

你混淆了对象与内容(项目)的变化的变化(列表本身)。 OnChangeSelectedItems只会在列表对象改变时被调用。

在change方法中,您可以测试集合是否实现INotifyCollectionChanged并手动处理后续更改。

编辑

您希望在执行上的项目更新的一些操作来访问上下文用户控件。这意味着您需要为CollectionChanged事件创建专门的处理程序实例。此外,您需要跟踪处理程序,以便稍后在出于某种原因将列表换出时将其删除。以下代码示例中的CurrentHandlers完成此操作。 代码以注册为收集相关的改变可能看起来像这样:

private static Dictionary<INotifyCollectionChanged, NotifyCollectionChangedEventHandler> CurrentHandlers = new Dictionary<INotifyCollectionChanged, NotifyCollectionChangedEventHandler>(); 

private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var usercontrol = d as MyCustomControl; 
    var selected = e.NewValue as IList; 

    var oldObservable = e.OldValue as INotifyCollectionChanged; 
    var newObservable = e.NewValue as INotifyCollectionChanged; 
    NotifyCollectionChangedEventHandler handler; 
    if (oldObservable != null && CurrentHandlers.TryGetValue(oldObservable, out handler)) 
    { 
     oldObservable.CollectionChanged -= handler; 
     CurrentHandlers.Remove(oldObservable); 
    } 
    if (newObservable != null) 
    { 
     handler = new NotifyCollectionChangedEventHandler((sender, e2) => SelectedItemsContentChanged(sender, e2, usercontrol)); 
     newObservable.CollectionChanged += handler; 
     CurrentHandlers.Add(newObservable, handler); 
    } 

    if (selected != null && selected.Count > 1) 
    { 
     //do something 
    } 
} 

private static void SelectedItemsContentChanged(object sender, NotifyCollectionChangedEventArgs e, MyCustomControl usercontrol) 
{ 
    //do something 
} 

注意,这(在前面的例子不同)是不是真的健壮。如果多次绑定相同的列表,CurrentHandlers存储将无法按预期工作。所以一定要选择一个处理程序存储机制,它可以安全地处理您的属性的使用案例。

一个想法,可能工作:var keyTuple = Tuple.Create(usercontrol, oldObservable);(或newObservable)作为CurrentHandlers字典的关键。

+0

是的,我也这么认为,但我怎么能实现它,因为列表没有实现INotifyCollectionChanged。我试着将IList更改为observableCollection 但它没有帮助。 – TRS

+1

@TRS查看我的编辑。 – grek40

+0

谢谢,这似乎工作,但我访问的用户控件作为依赖项对象参数在我的更改处理程序中的一部分,但我不能在SelectedItemsContentChanged中访问,并且“this”关键字不允许,因为static.Can你sugesst如何做(请参阅我的问题中的代码编辑) – TRS