在IList依赖属性上调用的更改方法

时间:2017-04-04 06:31:16

标签: c# wpf dependency-properties

我有一个自定义控件,我有一个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];
         }              

    }

这个Dependency属性绑定到Viewmodel中的一个可观察集合,我的问题是如果我在Viewmodel的构造函数中添加一些视图模型observable集合OnChangeSelectedItems被调用,但是如果我在运行时在observable集合中添加更多项目,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
    }

1 个答案:

答案 0 :(得分:3)

您将对象(列表本身)的更改与内容更改(项目)混淆。只有在更改列表对象时才会调用OnChangeSelectedItems

在更改方法中,您可以测试集合是否实现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词典的关键。