Search code examples
c#wpfxamldata-bindingoxyplot

WPF: Dependency property for usercontrol


OK, I don't get it and I know, this question has been asked and answered at least 10000 times.... but maybe I have some kind of special case here or I just don't get it.

I have a usercontrol that is is called Statisticspopup and it has a DependencyProperty as shown here:

public static readonly DependencyProperty XValueProperty = DependencyProperty.Register(
    "XValue", typeof(double), typeof(Statisticspopup),
    new FrameworkPropertyMetadata(XValueChanged));

public double XValue
{
    get
    {
        var x = GetValue(XProperty);
        return (double)x;
    }
    set
    {
        SetValue(XProperty, value);
    }
}

private static void XValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (Statisticspopup)d;
    control.XValue = double.Parse(e.NewValue.ToString());
    System.Diagnostics.Debug.WriteLine("XValueChanged");
}

I use it in my xaml code like this:

<controls:Statisticspopup XValue="42" />

This works and everything is fine... Now I want to use a binding for the property, something like this:

<controls:Statisticspopup XValue="{Binding DataPoint.X,PresentationTraceSources.TraceLevel=High}" />

The DataPoint.X value is from another control (OxyPlot object), so the whole code looks like this:

<oxy:Plot x:Name="PlotThing" Title="{Binding Title}"  Style="{DynamicResource PlotStyle}" >
    <oxy:Plot.TrackerDefinitions>
        <oxy:TrackerDefinition TrackerKey="someKey" >
            <oxy:TrackerDefinition.TrackerTemplate>
                <ControlTemplate>
                    <oxy:TrackerControl Name="TrackerControl" DataContext="{Binding }" Position="{Binding Position}" LineExtents="{Binding PlotModel.PlotArea}">
                        <oxy:TrackerControl.Content>     

<controls:Statisticspopup XValue="{Binding DataPoint.X,PresentationTraceSources.TraceLevel=High}" />
<TextBlock Foreground="Aquamarine" Text="{Binding DataPoint.X, PresentationTraceSources.TraceLevel=High}"></TextBlock>
....

As you can see, I also added a TextBlock to the TrackerControl.Content tag. Unfortunately the TextBlock shows the correct value, but I don't receive the binding in my usercontrol.

I get this output error:

BindingExpression path error: 'DataPoint' property not found on 'object' ''StatisticspopupViewModel' (HashCode=3740464)'.
BindingExpression:Path=DataPoint.X; DataItem='StatisticspopupViewModel' (HashCode=3740464); target element is 'Statisticspopup' (Name=''); target property is 'XValue' (type 'Double')

If I have a look to the TextBox, everything is ok.

I think it is somehow related to the Binding.Path property, as it tries to access the StatisticspopupViewModel which is definitely wrong. The output from the TextBox:

  • At level 0 - for TrackerHitResult.DataPoint found accessor ReflectPropertyDescriptor(DataPoint)
  • Replace item at level 0 with TrackerHitResult, using accessor ReflectPropertyDescriptor(DataPoint)
  • GetValue at level 0 from TrackerHitResult using ReflectPropertyDescriptor(DataPoint): DataPoint
  • At level 1 - for DataPoint.X found accessor ReflectPropertyDescriptor(X)
  • Replace item at level 1 with DataPoint , using accessor ReflectPropertyDescriptor(X)
  • GetValue at level 1 from DataPoint using ReflectPropertyDescriptor(X): '9' TransferValue - got raw value '9'
  • TransferValue - implicit converter produced '9'
  • TransferValue - using final value '9'

An finally the value is displayed...

Any idea for this issue?


Solution

  • Ok, I got it working. If I remove the ViewModel binding, the code is able to set the dependency properties and to use them in the correct way. This post here explains how to do it.