自定义控件中的依赖项属性意外地共享内存/值
我有以下设置:
- 自定义WPF控件(基类),派生自
Canvas
- 该基类的实现
- 该实现的
ObservableCollection
依赖项属性
我有一个测试应用程序,显示我的自定义控件的三个唯一实例(例如 ,Test2,Test3等)。 当我运行并调试应用程序时,
ObservableCollection
的内容对于控件的所有三个实例都是相同的。 为什么是这样?
图表:
[ContentProperty("DataGroups")] public abstract class Chart : Canvas { static Chart() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Chart), new FrameworkPropertyMetadata(typeof(Chart))); } public ObservableCollection DataGroups { get { return (ObservableCollection)GetValue(DataGroupsProperty); } set { SetValue(DataGroupsProperty, value); } } public static readonly DependencyProperty DataGroupsProperty = DependencyProperty.Register("DataGroups", typeof(ObservableCollection), typeof(Chart), new FrameworkPropertyMetadata(new ObservableCollection(), FrameworkPropertyMetadataOptions.AffectsArrange)); public abstract void Refresh(); }
ChartData:
[ContentProperty("Points")] public class ChartData : FrameworkElement { public ObservableCollection Points { get { return (ObservableCollection)GetValue(PointsProperty); } set { SetValue(PointsProperty, value); } } public static readonly DependencyProperty PointsProperty = DependencyProperty.Register("Points", typeof(ObservableCollection), typeof(ChartData), new PropertyMetadata(new ObservableCollection())); }
我修改图表数据的一种方法是(假设有多个数据组),例如:
MyChart.DataGroups[index].Points.Add(new Point() { Y = someNumber }); MyChart.Refresh();
但是DataGroups[]
每个实例都是相同的。
如果我通过XAML定义我的集合,也会发生同样的事情,如下所示:
然后,在代码中,我将访问已定义的集合:
ChartA.DataGroups[0].Points.Add(new Point() { Y = someNumber }); ChartA.Refresh();
你没有做错任何事。 这是设计的。 它应该那样工作。 只需在构造函数中设置您的值,您就不会有单例。
http://msdn.microsoft.com/en-us/library/aa970563.aspx
初始化超出默认值的集合
创建依赖项属性时,不要将属性默认值指定为初始字段值。 而是通过依赖项属性元数据指定默认值。 如果属性是引用类型,则依赖项属性元数据中指定的缺省值不是每个实例的缺省值; 相反,它是一个适用于该类型的所有实例的默认值。 因此,您必须小心不要将集合属性元数据定义的单一静态集合用作新创建的类型实例的工作默认值。 相反,您必须确保将集合值有意地设置为唯一(实例)集合,作为类构造函数逻辑的一部分。 否则你将创建一个无意的单例类。
PointsProperty
是一个静态值,使用默认值new ObservableCollection
初始化。 此静态初始值设定项创建单个ObservableCollection
,并将其用作您创建的ChartData
类型的任何对象上的Points
的默认值。 它不是为每个需要默认值的实例创建新的ObservableCollection
的工厂。 它只是为每个使用相同的ObservableCollection
。
我猜你从未明确地为Points
赋值,因此总是依赖于默认值,该值在所有实例中共享。 这就是为什么每个实例都有相同的点集合。