Cam*_*ers 1 c# collections wpf notifications
我有一个 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>();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们为其中一个 FieldHeadings 的 Layout 分配一个新值,不会生成任何更改通知。显然我错过了一些重要的事情。HeadingChanged 永远不会被调用。
有关 FreezableCollection 的 MSDN 帮助可在此处找到:FreezableCollection,其中指出:
事件更改... 当 Freezable 或其包含的对象被修改时发生。(继承自 Freezable。)
预先感谢您的任何帮助。
〜卡梅伦
事实上,你可以做你想做的事。这正是FreezableCollection<T>存在的原因!您需要做的就是更改FieldHeading为派生自Freezable而不是DependencyObject对集合中的项目进行更改将给出相同的更改通知,就像整个项目已被替换一样。
这是一个非常有用但鲜为人知的 WPF 功能。
当然,每当向集合添加或从集合中删除项目时,这些可冻结集合类都会发出更改通知,而且当集合中任何项目的依赖属性发生更改时也会发出更改通知。这是一个极其强大的机制。
这是一个演示如何使用的小示例FreezableCollection<>。我在 Visual Studio 中创建了一个新的 WPF 项目。以下是MainWindow.xaml.cs的 XAML及其背后的 C# 代码:
<Window x:Class="FreezableCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FreezableCollection"
x:Name="Root"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type local:MyFreezable}">
<CheckBox IsChecked="{Binding IsNice}" Content="Check me!"/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding ElementName=Root, Path=MyFreezables}" />
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
using System.Windows;
namespace FreezableCollection
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty MyFreezablesProperty =
DependencyProperty.Register("MyFreezables", typeof(MyFreezableCollection), typeof(MainWindow), new FrameworkPropertyMetadata(null, FreezablesChangedCallback));
public MyFreezableCollection MyFreezables
{
get => (MyFreezableCollection)GetValue(MyFreezablesProperty);
set => SetValue(MyFreezablesProperty, value);
}
public MainWindow()
{
InitializeComponent();
MyFreezables = new MyFreezableCollection { new MyFreezable() };
}
private static void FreezablesChangedCallback(object sender, DependencyPropertyChangedEventArgs args)
{
MessageBox.Show("Changed!");
}
}
public class MyFreezableCollection : FreezableCollection<MyFreezable>
{
protected override Freezable CreateInstanceCore() => new MyFreezableCollection();
}
public class MyFreezable : Freezable
{
public static readonly DependencyProperty IsNiceProperty =
DependencyProperty.Register("IsNice", typeof(bool), typeof(MyFreezable), new PropertyMetadata(false));
public bool IsNice
{
get => (bool)GetValue(IsNiceProperty);
set => SetValue(IsNiceProperty, value);
}
protected override Freezable CreateInstanceCore() => new MyFreezable();
}
}
Run Code Online (Sandbox Code Playgroud)
该示例显示一个包含单个CheckBox. 单击它可以切换IsNice数据绑定中项目的属性MyFreezableCollection。即使列表中没有添加或删除任何内容,也会调用依赖属性更改回调。