自定义控件中的依赖项属性意外地共享内存/值

qJa*_*ake 4 c# wpf dependency-properties custom-controls

我有以下设置:

  • 自定义WPF控件(基类),派生自 Canvas
  • 该基类的实现
  • ObservableCollection<T>该实现的依赖属性

我有一个测试应用程序,显示我的自定义控件的三个唯一实例(例如<custom:MyControl x:Name="Test1" />,Test2,Test3等).当我运行并调试应用程序时,ObservableCollection<T>控件的所有三个实例的内容都是相同的.为什么是这样?


图表:

[ContentProperty("DataGroups")]
public abstract class Chart : Canvas
{
    static Chart()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Chart), new FrameworkPropertyMetadata(typeof(Chart)));
    }

    public ObservableCollection<ChartData> DataGroups
    {
        get { return (ObservableCollection<ChartData>)GetValue(DataGroupsProperty); }
        set { SetValue(DataGroupsProperty, value); }
    }
    public static readonly DependencyProperty DataGroupsProperty =
        DependencyProperty.Register("DataGroups", typeof(ObservableCollection<ChartData>), typeof(Chart), new FrameworkPropertyMetadata(new ObservableCollection<ChartData>(), FrameworkPropertyMetadataOptions.AffectsArrange));

    public abstract void Refresh();
}
Run Code Online (Sandbox Code Playgroud)

ChartData:

[ContentProperty("Points")]
public class ChartData : FrameworkElement
{
    public ObservableCollection<Point> Points
    {
        get { return (ObservableCollection<Point>)GetValue(PointsProperty); }
        set { SetValue(PointsProperty, value); }
    }
    public static readonly DependencyProperty PointsProperty =
        DependencyProperty.Register("Points", typeof(ObservableCollection<Point>), typeof(ChartData), new PropertyMetadata(new ObservableCollection<Point>()));
}
Run Code Online (Sandbox Code Playgroud)

我修改图表数据的一种方法是(假设有多个数据组),例如:

MyChart.DataGroups[index].Points.Add(new Point() { Y = someNumber });
MyChart.Refresh();
Run Code Online (Sandbox Code Playgroud)

但内部的每个实例DataGroups[]都是相同的.


如果我通过XAML定义我的集合,也会发生同样的事情,如下所示:

<c:Chart x:Name="ChartA">
    <c:ChartData x:Name="DataGroup1" />
    <c:ChartData x:Name="DataGroup2" />
</c:Chart>
Run Code Online (Sandbox Code Playgroud)

然后,在代码中,我将访问已定义的集合:

ChartA.DataGroups[0].Points.Add(new Point() { Y = someNumber });
ChartA.Refresh();
Run Code Online (Sandbox Code Playgroud)

dev*_*hog 9

你没有做错任何事.这是设计的.它应该那样工作.只需在构造函数中设置您的值,您就不会有单例.

http://msdn.microsoft.com/en-us/library/aa970563.aspx

初始化超出默认值的集合

创建依赖项属性时,不要将属性默认值指定为初始字段值.而是通过依赖项属性元数据指定默认值.如果您的属性是引用类型,则依赖项属性元数据中指定的默认值不是每个实例的默认值; 相反,它是一个默认值,适用于该类型的所有实例.因此,您必须小心不要将集合属性元数据定义的单一静态集合用作新创建的类型实例的工作默认值.相反,您必须确保将集合值有意地设置为唯一(实例)集合,作为类构造函数逻辑的一部分.否则你将创建一个无意的单例类.