WPF:用户控件的依赖项 属性
WPF: Dependency property for usercontrol
好吧,我不明白,我知道,这个问题已经被问到并回答了至少 10000 次....但也许我这里有某种特殊情况,或者我只是不明白.
我有一个名为 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");
}
我在我的 xaml 代码中这样使用它:
<controls:Statisticspopup XValue="42" />
这有效,一切都很好...现在我想为 属性 使用绑定,如下所示:
<controls:Statisticspopup XValue="{Binding DataPoint.X,PresentationTraceSources.TraceLevel=High}" />
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>
....
如您所见,我还在 TrackerControl.Content 标签中添加了一个 TextBlock。不幸的是,TextBlock 显示了正确的值,但我没有在我的用户控件中收到绑定。
我得到这个输出错误:
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')
如果我查看 TextBox,一切正常。
我认为它与 Binding.Path
属性 有某种关系,因为它试图访问 StatisticspopupViewModel
,这肯定是错误的。文本框的输出:
- 在级别 0 - TrackerHitResult.DataPoint 找到访问者
ReflectPropertyDescriptor(数据点)
- 使用访问器将级别 0 的项目替换为 TrackerHitResult
ReflectPropertyDescriptor(数据点)
- 使用 TrackerHitResult 在级别 0 处获取值
ReflectPropertyDescriptor(数据点):数据点
- 在第 1 级 - DataPoint.X 找到访问器
ReflectPropertyDescriptor(X)
- 使用访问器将级别 1 的项目替换为 DataPoint
ReflectPropertyDescriptor(X)
- 使用 DataPoint 在第 1 级获取值
ReflectPropertyDescriptor(X): '9' TransferValue - 得到原始值 '9'
- TransferValue - 隐式转换器生成“9”
- TransferValue - 使用最终值“9”
最后显示值...
对这个问题有什么想法吗?
您的 PropertyChangedCallback 已损坏。它不能包含行
control.XValue = double.Parse(e.NewValue.ToString());
顺便说一句。应该看起来像 control.XValue = (double)e.NewValue;
该方法是 XValue
属性 的 "changed" 回调,因此在 属性 值已经更改时调用。它不应该(也不能)再次设置该值,因为这有效地从 属性.
中删除了 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);
}
好的,我成功了。如果我删除 ViewModel 绑定,代码就能够设置依赖属性并以正确的方式使用它们。
This post here 说明如何操作。
好吧,我不明白,我知道,这个问题已经被问到并回答了至少 10000 次....但也许我这里有某种特殊情况,或者我只是不明白.
我有一个名为 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");
}
我在我的 xaml 代码中这样使用它:
<controls:Statisticspopup XValue="42" />
这有效,一切都很好...现在我想为 属性 使用绑定,如下所示:
<controls:Statisticspopup XValue="{Binding DataPoint.X,PresentationTraceSources.TraceLevel=High}" />
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>
....
如您所见,我还在 TrackerControl.Content 标签中添加了一个 TextBlock。不幸的是,TextBlock 显示了正确的值,但我没有在我的用户控件中收到绑定。
我得到这个输出错误:
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')
如果我查看 TextBox,一切正常。
我认为它与 Binding.Path
属性 有某种关系,因为它试图访问 StatisticspopupViewModel
,这肯定是错误的。文本框的输出:
- 在级别 0 - TrackerHitResult.DataPoint 找到访问者 ReflectPropertyDescriptor(数据点)
- 使用访问器将级别 0 的项目替换为 TrackerHitResult ReflectPropertyDescriptor(数据点)
- 使用 TrackerHitResult 在级别 0 处获取值 ReflectPropertyDescriptor(数据点):数据点
- 在第 1 级 - DataPoint.X 找到访问器 ReflectPropertyDescriptor(X)
- 使用访问器将级别 1 的项目替换为 DataPoint ReflectPropertyDescriptor(X)
- 使用 DataPoint 在第 1 级获取值 ReflectPropertyDescriptor(X): '9' TransferValue - 得到原始值 '9'
- TransferValue - 隐式转换器生成“9”
- TransferValue - 使用最终值“9”
最后显示值...
对这个问题有什么想法吗?
您的 PropertyChangedCallback 已损坏。它不能包含行
control.XValue = double.Parse(e.NewValue.ToString());
顺便说一句。应该看起来像 control.XValue = (double)e.NewValue;
该方法是 XValue
属性 的 "changed" 回调,因此在 属性 值已经更改时调用。它不应该(也不能)再次设置该值,因为这有效地从 属性.
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);
}
好的,我成功了。如果我删除 ViewModel 绑定,代码就能够设置依赖属性并以正确的方式使用它们。 This post here 说明如何操作。