【问题标题】:changed method not called on IList dependency property [duplicate]未在 IList 依赖属性上调用更改的方法 [重复]
【发布时间】:2017-04-04 06:31:16
【问题描述】:

我有一个自定义控件,其中有一个 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 的构造函数中添加一些项目在视图模型可观察集合中 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
    }

【问题讨论】:

  • @Clemens 虽然肯定是重复的,但我认为链接的 Q/A 缺少一个好的标题,无法作为参考。

标签: c# wpf dependency-properties


【解决方案1】:

您将对象(列表本身)的更改与内容(项目)的更改混淆了。 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 字典的键。

【讨论】:

  • 是的,我也这么认为,但是我怎么能实现它,因为 List 没有实现 INotifyCollectionChanged 。我尝试将 IList 更改为 observableCollection 但它没有帮助。
  • @TRS 查看我的编辑。
  • 谢谢,这似乎有效,但我正在访问作为更改处理程序中依赖对象参数的一部分的用户控件,但我无法在 SelectedItemsContentChanged 中访问它,并且由于静态,也不允许使用“this”关键字.你能建议怎么做吗(请参阅我的问题中的代码编辑)
  • @TRS 以防您没有注意到:我再次编辑了您关于访问用户控件的附加要求。
  • @TRS 实际上,只要处理程序方法在逻辑上属于用户控件,您的解决方案就很好。我的建议更多的是一种通用方法,如果属性/处理程序不是用户控件的一部分(如附加属性方案)但它不是内部处理程序的最佳选择。
猜你喜欢
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多