简体   繁体   English

WPF:用户控件的依赖项属性

[英]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. 好的,我不明白,我知道,这个问题至少被问过并回答10000次。...但是也许我在这里有某种特殊情况,或者我只是不明白。

I have a usercontrol that is is called Statisticspopup and it has a DependencyProperty as shown here: 我有一个名为Statisticspopup的用户控件,它具有DependencyProperty ,如下所示:

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: 我在我的xaml代码中使用它,如下所示:

<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: DataPoint.X值来自另一个控件(OxyPlot对象),因此整个代码如下所示:

<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. 如您所见,我还向TrackerControl.Content标记添加了一个TextBlock。 Unfortunately the TextBlock shows the correct value, but I don't receive the binding in my usercontrol. 不幸的是,TextBlock显示了正确的值,但是我的用户控件中没有收到绑定。

I get this output error: 我收到此输出错误:

BindingExpression path error: 'DataPoint' property not found on 'object' ''StatisticspopupViewModel' (HashCode=3740464)'. BindingExpression路径错误:在“对象”“ StatisticspopupViewModel”(HashCode = 3740464)”上找不到“ DataPoint”属性。
BindingExpression:Path=DataPoint.X; BindingExpression:路径= DataPoint.X; DataItem='StatisticspopupViewModel' (HashCode=3740464); DataItem ='StatisticspopupViewModel'(HashCode = 3740464); target element is 'Statisticspopup' (Name=''); 目标元素是'Statisticspopup'(Name =''); target property is 'XValue' (type 'Double') 目标属性为“ XValue”(类型为“ Double”)

If I have a look to the TextBox, everything is ok. 如果我看看TextBox,一切都很好。

I think it is somehow related to the Binding.Path property, as it tries to access the StatisticspopupViewModel which is definitely wrong. 我认为这与Binding.Path属性有关,因为它尝试访问StatisticspopupViewModel ,这肯定是错误的。 The output from the TextBox: TextBox的输出:

  • At level 0 - for TrackerHitResult.DataPoint found accessor ReflectPropertyDescriptor(DataPoint) 在级别0处-为TrackerHitResult.DataPoint找到了访问者ReflectPropertyDescriptor(DataPoint)
  • Replace item at level 0 with TrackerHitResult, using accessor ReflectPropertyDescriptor(DataPoint) 使用访问器ReflectPropertyDescriptor(DataPoint)将级别0的项目替换为TrackerHitResult
  • GetValue at level 0 from TrackerHitResult using ReflectPropertyDescriptor(DataPoint): DataPoint 使用ReflectPropertyDescriptor(DataPoint)从TrackerHitResult获得0级的GetValue:DataPoint
  • At level 1 - for DataPoint.X found accessor ReflectPropertyDescriptor(X) 在级别1-对于DataPoint.X,找到了访问者ReflectPropertyDescriptor(X)
  • Replace item at level 1 with DataPoint , using accessor ReflectPropertyDescriptor(X) 使用访问器ReflectPropertyDescriptor(X)将第1级的项目替换为DataPoint
  • GetValue at level 1 from DataPoint using ReflectPropertyDescriptor(X): '9' TransferValue - got raw value '9' 使用ReflectPropertyDescriptor(X)从DataPoint处获取第1级的GetValue:'9'TransferValue-获得原始值'9'
  • TransferValue - implicit converter produced '9' TransferValue-隐式转换器产生的“ 9”
  • TransferValue - using final value '9' TransferValue-使用最终值“ 9”

An finally the value is displayed... 最终显示值...

Any idea for this issue? 对这个问题有什么想法吗?

Your PropertyChangedCallback is broken. 您的PropertyChangedCallback已损坏。 It must not contain the line 它不能包含行

control.XValue = double.Parse(e.NewValue.ToString());

which btw. 顺便说一句。 should be looking like control.XValue = (double)e.NewValue; 应该看起来像control.XValue = (double)e.NewValue;

The method is a "changed" callback for the XValue property, and therefore called when the property value has already change. 该方法是XValue属性的“已更改”回调,因此在属性值已更改时调用。 It should not (and must not) set the value again, because this effectivly removes the Binding from the property. 它不应(也不得)再次设置该值,因为这会有效地从属性中删除Binding。

private static void XValueChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (Statisticspopup)d;

    // here control.XValue is already identical to (double)e.NewValue;

    Debug.WriteLine("XValueChanged: {0}, {1}", e.NewValue, control.XValue);
}

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. 如果删除ViewModel绑定,则代码可以设置依赖项属性并以正确的方式使用它们。 This post here explains how to do it. 这篇文章在这里解释了如何做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM