wpf 删除集合中的项时,ObservableCollection依赖项属性不更新

sigwle7e  于 2023-02-10  发布在  其他
关注(0)|答案(3)|浏览(289)

我在控件上附加了ObservableCollection类型的属性。如果我在集合中添加或移除项,则UI不会更新。但是,如果我将其中的集合替换为ViewModel中的新集合,则UI会更新。
有人能给予我一个例子,说明我需要在Dependency对象中做些什么,以便它能够处理集合中的更改吗?
部分依赖对象如下所示:

public class RadCalendarBehavior : DependencyObject
{
private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  var calendar = d as RadCalendar;
  if (e.NewValue != null)
  {
    calendar.DayTemplateSelector = new SpecialDaySelector((ObservableCollection<DateTime>)e.NewValue, GetSpecialDayTemplate(d));
  }
}

public static ObservableCollection<DateTime> GetSpecialDays(DependencyObject obj)
{
  return (ObservableCollection<DateTime>)obj.GetValue(SpecialDaysProperty);
}

public static void SetSpecialDays(DependencyObject obj, ObservableCollection<DateTime> value)
{
  obj.SetValue(SpecialDaysProperty, value);
}

public static readonly DependencyProperty SpecialDaysProperty =
    DependencyProperty.RegisterAttached("SpecialDays", typeof(ObservableCollection<DateTime>), typeof(RadCalendarBehavior), new UIPropertyMetadata(null, OnSpecialDaysChanged));
}
}

我知道需要注册集合已更改,但不确定如何在dependency属性中执行此操作

pbwdgjma

pbwdgjma1#

集合中的更改不会触发OnSpecialDaysChanged回调,因为dependency属性的值没有更改。如果需要对检测到的集合更改做出React,则需要手动处理CollectionChanged事件:

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  var calendar = d as RadCalendar;

  if (e.OldValue != null)
  {
    var coll = (INotifyCollectionChanged)e.OldValue;
    // Unsubscribe from CollectionChanged on the old collection
    coll.CollectionChanged -= SpecialDays_CollectionChanged;
  }

  if (e.NewValue != null)
  {
    var coll = (ObservableCollection<DateTime>)e.NewValue;
    calendar.DayTemplateSelector = new SpecialDaySelector(coll, GetSpecialDayTemplate(d));
    // Subscribe to CollectionChanged on the new collection
    coll.CollectionChanged += SpecialDays_CollectionChanged;
  }
}

private static void SpecialDays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // handle CollectionChanged
}
bnl4lu3b

bnl4lu3b2#

这只是补充托马斯的回答。在我的代码中,我通过在本地创建一个handler对象来与DependencyObject的属性交互,如下所示:

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var action = new NotifyCollectionChangedEventHandler(
            (o, args) =>
                {
                    var calendar = d as RadCalendar;

                    if (calendar!= null)
                    {
                        // play with calendar's properties/methods
                    }
                });

    if (e.OldValue != null)
    {
       var coll = (INotifyCollectionChanged)e.OldValue;
       // Unsubscribe from CollectionChanged on the old collection
       coll.CollectionChanged -= action;
    }

    if (e.NewValue != null)
    {
       var coll = (ObservableCollection<DateTime>)e.NewValue;
       // Subscribe to CollectionChanged on the new collection
       coll.CollectionChanged += action;
    }
}

希望这对某人有帮助。

eh57zj3b

eh57zj3b3#

如果具有集合类型的依赖项属性,请记住以下几点:
如果属性是引用类型,则依赖项属性元数据中指定的默认值不是每个示例的默认值;相反,它是一个默认值,适用于该类型的所有示例。[...]
若要更正此问题,必须将集合依赖项属性值重置为唯一示例,作为类构造函数调用的一部分。
(see MSDN第一版)
为了回答山姆的问题(我刚刚遇到了同样的问题):
使CollectionChanged-handler是非静态的,并在示例级别取消订阅/重新订阅。

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  var calendar = (RadCalendar)d;

  if (e.OldValue != null)
  {
    var coll = (INotifyCollectionChanged)e.OldValue;
    // Unsubscribe from CollectionChanged on the old collection of the DP-instance (!)
    coll.CollectionChanged -= calendar.SpecialDays_CollectionChanged;
  }

  if (e.NewValue != null)
  {
    var coll = (ObservableCollection<DateTime>)e.NewValue;
    calendar.DayTemplateSelector = new SpecialDaySelector(coll, GetSpecialDayTemplate(d));
    // Subscribe to CollectionChanged on the new collection of the DP-instance (!)
    coll.CollectionChanged += calendar.SpecialDays_CollectionChanged;
  }
}

private void SpecialDays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // handle CollectionChanged on instance-level
}

相关问题