2010-12-06 124 views
21

我在控件上附加了ObservableCollection类型的属性。如果我添加或删除集合中的项目,则ui不会更新。但是,如果我用一个新的ViewModel替换内部的集合,UI就会更新。当删除集合中的项目时,ObservableCollection依赖项属性不会更新

有人可以给我一个我需要在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)); 
} 
} 

我明白,我需要注册该集合发生了变化,但我不能确定如何依赖属性

回答

33

A内做到这一点集合中的更改不会触发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 
} 
+0

谢谢。是否有可能在SpecialDays_CollectionChanged中获得依赖对象的引用? – GoalMaker 2010-12-06 01:20:07

+0

哪个依赖对象?你的意思是RadCalendar?不容易...无论如何,我不确定它是否合理:如果RadCalendar的多个实例绑定到相同的集合? – 2010-12-06 01:30:57

5

这仅仅是添加到托马斯的答案。在我的代码我通过localy创建一个处理程序对象像下面与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

如果你有一个集合类型依赖项属性请注意以下几点:

如果你的财产是引用类型,在依赖项属性的元数据中指定的默认值是不是每个实例的默认值;相反,它是一个默认值,适用于该类型的所有实例。 [...]
要解决此问题,必须将集合依赖项属性值重置为唯一实例,作为类构造函数调用的一部分。

(参见MSDN Collection-Type Dependency Properties

要回答Sam的问题(我只是碰到了同样的问题):

让你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 of the DP-instance (!) 
    coll.CollectionChanged -= d.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 += d.SpecialDays_CollectionChanged; 
    } 
} 

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