首页 文章

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

提问于
浏览
4

我有以下设置:

  • 自定义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();
}

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>()));
}

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

MyChart.DataGroups[index].Points.Add(new Point() { Y = someNumber });
MyChart.Refresh();

DataGroups[] 中的每个实例都是相同的 .


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

<c:Chart x:Name="ChartA">
    <c:ChartData x:Name="DataGroup1" />
    <c:ChartData x:Name="DataGroup2" />
</c:Chart>

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

ChartA.DataGroups[0].Points.Add(new Point() { Y = someNumber });
ChartA.Refresh();

2 回答

  • 9

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

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

    初始化超出默认值的集合

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

  • 1

    PointsProperty 是使用默认值 new ObservableCollection<Point>() 初始化的静态值 . 此静态初始值设定项创建单个 ObservableCollection ,并在您创建的任何类型为 ChartData 的对象上将其用作 Points 的默认值 . 它不是为每个需要默认值的实例创建新 ObservableCollection 的工厂;它只是为每个使用相同的 ObservableCollection .

    我猜你从未明确地为 Points 分配一个值,因此总是依赖于默认值,该值在所有实例中共享 . 这就是为什么每个实例都有相同的点集合 .

相关问题