我在控件上有一个ObservableCollection类型的附加属性。如果我在集合中添加或删除项目,则ui不会更新。但是,如果我用一个新的替换集合,那么ui会更新ViewModel。
有人能给我一个我在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));
}
}
我知道我需要注册该集合已更改,但我不确定如何在依赖属性中执行此操作
答案 0 :(得分:36)
集合中的更改不会触发OnSpecialDaysChanged
回调,因为依赖项属性的值未更改。如果您需要做出反应以检测集合的更改,则需要手动处理事件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
}
答案 1 :(得分:5)
这只是为了补充托马斯的答案。在我的代码中,我通过创建一个类似于下面的处理程序对象来与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;
}
}
希望这对某人有帮助。
答案 2 :(得分:3)
如果您有一个集合类型依赖项属性,请记住以下几点:
如果您的属性是引用类型,则依赖项属性元数据中指定的默认值不是每个实例的默认值;相反,它是一个默认值,适用于该类型的所有实例。 [...]
要解决此问题,必须将集合依赖项属性值重置为唯一实例,作为类构造函数调用的一部分。
(请参阅MSDN Collection-Type Dependency Properties)
回答Sam的问题(我遇到了同样的问题):
使您的CollectionChanged-handler非静态,并在实例级别取消订阅/重新订阅。
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 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
}