Dependency property in custom control is sharing memory/values unexpectedly

梦想与她 提交于 2020-01-03 20:01:56

问题


I have the following set up:

  • Custom WPF Control (Base class), deriving from Canvas
  • Implementation of that base class
  • An ObservableCollection<T> dependency property on that implementation

I have a test app that displays three unique instances of my custom control (e.g. <custom:MyControl x:Name="Test1" />, Test2, Test3, and so on). When I run and debug the app, the contents of the ObservableCollection<T> are the same for all three instances of the control. Why is this?


Chart:

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

One way I modify the chart data is (assuming multiple data groups), for example:

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

But every instance inside DataGroups[] is identical.


The same thing is happening if I define my collection(s) via XAML, like so:

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

Then, in code, I would access the defined collections:

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

回答1:


You havent done anything wrong. It is by design. It shall work that way. Just set your value in constructor instead and you will not have a singleton.

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

Initializing the Collection Beyond the Default Value

When you create a dependency property, you do not specify the property default value as the initial field value. Instead, you specify the default value through the dependency property metadata. If your property is a reference type, the default value specified in dependency property metadata is not a default value per instance; instead it is a default value that applies to all instances of the type. Therefore you must be careful to not use the singular static collection defined by the collection property metadata as the working default value for newly created instances of your type. Instead, you must make sure that you deliberately set the collection value to a unique (instance) collection as part of your class constructor logic. Otherwise you will have created an unintentional singleton class.




回答2:


PointsProperty is a static value that you initialize with a default value of new ObservableCollection<Point>(). This static initializer creates a single ObservableCollection and uses that as the default value for Points on any object of type ChartData that you create. It is not a factory that creates new ObservableCollections for every instance that needs a default value; it simply uses the same ObservableCollection for each.

I'm guessing that you never explicitly assign a value to Points, thus always relying on the default value, which is shared across all instances. That's why each instance has the same collection of points.



来源:https://stackoverflow.com/questions/19217208/dependency-property-in-custom-control-is-sharing-memory-values-unexpectedly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!