C# FreezableCollection在子属性更改时不提供更改通知

C# FreezableCollection在子属性更改时不提供更改通知,c#,wpf,collections,notifications,C#,Wpf,Collections,Notifications,我有一个FreezableCollection,我想监视它对子属性的更改。以下是守则的一个小节: public class FieldHeading : DependencyObject { public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register("Layout", typeof(FieldHeadingLayout), typeof(FieldHeading),

我有一个FreezableCollection,我想监视它对子属性的更改。以下是守则的一个小节:

public class FieldHeading : DependencyObject
{
    public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register("Layout", typeof(FieldHeadingLayout), typeof(FieldHeading),
        new FrameworkPropertyMetadata(FieldHeadingLayout.Above,
        FrameworkPropertyMetadataOptions.AffectsRender |
        FrameworkPropertyMetadataOptions.AffectsMeasure |
        FrameworkPropertyMetadataOptions.AffectsParentMeasure));

    public FieldHeadingLayout Layout
    {
        get { return (FieldHeadingLayout) GetValue(LayoutProperty); }
        set { SetValue(LayoutProperty, value); }
    }

}

public class FieldPanel : FrameworkElement
{
    private static readonly DependencyProperty FieldHeadingProperty = DependencyProperty.Register("FieldHeading", typeof(FreezableCollection<FieldHeading>), typeof(FieldPanel),
        new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.AffectsMeasure |
            FrameworkPropertyMetadataOptions.AffectsParentMeasure |
            FrameworkPropertyMetadataOptions.AffectsRender, HeadingChanged));

    private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("Hello");
    }

    public FreezableCollection<FieldHeading> FieldHeadings
    {
        get
        { return (FreezableCollection<FieldHeading>) GetValue(FieldHeadingProperty); }
        set { SetValue(FieldHeadingProperty, value);}
    }

    public FieldPanel()
    {
        AddVisual(_contentVisual = new DrawingVisual());
        FieldHeadings = new FreezableCollection<FieldHeading>();
    }
}
然后我们为其中一个字段标题的布局分配一个新值,不会生成更改通知。显然我错过了一些重要的事情。头永远不会变

有关FreezableCollection的MSDN帮助(可在此处找到)说明:

事件已更改。。。修改Freezable或其包含的对象时发生。继承自Freezable

提前感谢您的帮助


~Cameron

问题是,您只订阅FieldHeaders属性更改,这意味着您只有在有人使用FeilHeadings属性设置器分配集合本身的新实例时才会收到通知


为了在布局属性更改时接收通知,您必须在FieldHeading的每个实例上订阅它。

问题是您只订阅FieldHeaders属性更改,这意味着您只有在有人分配集合本身的新实例时才会收到通知,例如,Feilhedings属性设置器


为了在Layout属性更改时接收通知,您必须在FieldHeading的每个实例上订阅它。

更改通知处理程序仅在属性值更改时通知您,因此在这种情况下,如果freezable集合更改为新集合。在属性更改处理程序中,您需要订阅CollectionChanged事件,在该事件中,您需要订阅新项上的PropertyChanged事件。现在,最后,您有了一个事件,该事件将允许您对属于可冻结集合的项的属性更改做出反应,该集合是一个依赖项属性。请记住取消订阅旧集合和旧项目的事件。

更改通知处理程序仅在属性值更改时通知您,因此在这种情况下,如果可冻结集合更改为新集合,则更改通知处理程序将通知您。在属性更改处理程序中,您需要订阅CollectionChanged事件,在该事件中,您需要订阅新项上的PropertyChanged事件。现在,最后,您有了一个事件,该事件将允许您对属于可冻结集合的项的属性更改做出反应,该集合是一个依赖项属性。记得取消订阅旧收藏和旧物品的活动。

实际上,你可以做你想做的事情。这就是FreezableCollection存在的原因!您只需将FieldHeading更改为派生自Freezable而不是DependencyObject,对集合中的项所做的更改将发出与替换整个项相同的更改通知

这是一个非常有用且鲜为人知的WPF特性

,

当然,每当向集合中添加项或从集合中删除项时,以及当集合中任何项的依赖项属性发生更改时,这些freezable集合类都会触发更改通知。这是一个非常强大的机制

事实上,你可以做你想做的事。这就是FreezableCollection存在的原因!您只需将FieldHeading更改为派生自Freezable而不是DependencyObject,对集合中的项所做的更改将发出与替换整个项相同的更改通知

这是一个非常有用且鲜为人知的WPF特性

,

当然,每当向集合中添加项或从集合中删除项时,以及当集合中任何项的依赖项属性发生更改时,这些freezable集合类都会触发更改通知。这是一个非常强大的机制


此外,由于FieldHeading不可Freezable,因此使用FreezableCollection没有任何优势。你可以用一个ObservableCollection来代替。看起来你可以做OP描述的事情。有关详细信息,请参阅下面我与Charles Petzold帖子的链接。这是一个鲜为人知但很方便的WPF功能。但这是正确的:这取决于您是否能够将FieldHeading更改为派生自Freezable。此外,由于FieldHeading不可Freezable,因此使用FreezableCollection没有任何好处。你可以用一个ObservableCollection来代替。看起来你可以做OP描述的事情。有关详细信息,请参阅下面我与Charles Petzold帖子的链接。这是一个鲜为人知但很方便的WPF功能。但这是正确的:这取决于您是否能够更改FieldHeading以从Freezable派生。Downvoter,这对您不起作用吗?只是好奇:唐纳德,这对你不管用吗?只是好奇: