1

我有一个包含三个复选框和三个日期选择器的用户控件。例如,用户控件上的日期选择器之一看起来像这样(为清楚起见,删除了 Width 等不相关的属性)...

<telerik:RadDatePicker DisplayFormat="Long"
                       SelectedValue="{Binding DepositPaidDate, Mode=TwoWay}"/>

控件的视图模型有一个名为 PaidDate 的公共属性,其类型为 PaidDate(是的,该属性和类具有相同的名称),控件上的顶级 Grid 将其 DataContext 设置为 PaidDate 属性,并且Grid 中的各个控件绑定到此 PaidDate 对象的属性。

当在窗口上使用此控件,并且窗口的代码在控件的 VM 上显式设置 PaidDate 属性时,一切正常。例如,我创建了一个测试窗口,其构造函数如下所示...

public PaidDateWindow(PaidDate paidDate, string windowTitle) {
  InitializeComponent();
  ((PaidDateControlViewModel)PaidDateCtrl.DataContext).PaidDate = paidDate;
  Title = windowTitle;
}

...这工作得很好。我可以显示窗口,并且数据显示正确。

当我尝试通过控件上的依赖属性进行设置时,问题就来了。用户控件代码中的依赖属性如下所示...

public static readonly DependencyProperty PaidDateProperty = DependencyProperty.Register("PaidDate", typeof(PaidDate), typeof(PaidDateControl), new FrameworkPropertyMetadata(SetPaidDateStatic));

private static void SetPaidDateStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) {
  (d as PaidDateControl).SetPaidDate((PaidDate)e.NewValue);
}

private void SetPaidDate(PaidDate paidDate) {
  if (DataContext != null) {
    ((PaidDateControlViewModel)DataContext).PaidDate = paidDate;
  }
}

public PaidDate PaidDate {
  get {
    return (PaidDate)GetValue(PaidDateProperty);
  }
  set {
    SetValue(PaidDateProperty, value);
  }
}

如您所见,依赖属性只是将 PaidDate 对象传递给视图模型,这与我在前面的代码中手动执行此操作时的效果相同。

当我尝试将此依赖项属性绑定到窗口视图模型上的属性时,出现绑定错误。这是父窗口中的 XAML...

<vrtSystemsUserControls:PaidDateControl
  PaidDate="{Binding Path=VRTSystem.PaidDate, Mode=TwoWay}" />

父窗口的 VM 包含一个名为 VrtSystem 的属性,并且窗口上的许多其他控件都绑定到该属性。VrtSystem 还包含一个名为 PaidDate 的属性,这就是我想要传递给用户控件的属性。

但是,当我运行它时,我收到以下绑定错误...

System.Windows.Data Error: 40 : BindingExpression path error:
'VRTSystem' property not found on 'object' ''PaidDateControlViewModel' (HashCode=18319327)'.
BindingExpression:Path=VRTSystem.PaidDate; DataItem='PaidDateControlViewModel' (HashCode=18319327);
target element is 'PaidDateControl' (Name=''); target property is 'PaidDate' (type 'PaidDate')

现在它看起来好像 WPF 正在将实际绑定信息传递给用户控件,而不是 PaidDate 对象,因为错误表明它正在尝试在用户控件的 VM 上查找 VrtSystem 属性。我不知道为什么会这样做,因为我认为绑定的想法是在窗口级别解析绑定,然后将结果(即 PaidDate 对象)发送到依赖属性,它会在哪里发送到虚拟机。

我希望我已经清楚地解释了这一点。任何人都能够看到出了什么问题?

谢谢你的帮助。

4

1 回答 1

2

当您的绑定被解析时,它正在寻找它所应用到的控件的VRTSystem属性。DataContext

'DataContext' 属性由子控件继承,因此如果您在 aDataContext上设置 a,Window它的所有子控件都将具有相同的DataContext. 但是,如果其中一个孩子本身应用了不同的 DataContext,则它的所有孩子都将使用它。

在您的情况下,Window有 a DataContext,但UserControl. 因此,默认情况下,或它的孩子上的所有绑定UserControl都将期望找到在这种情况下不是您想要的VRTSystem属性。UserControls DataContext

因此,要显式定位 的DataContext,您必须通过设置它的属性Window来告诉绑定,如下所示:RelativeSource

{Binding Path=DataContext.VRTSystem.PaidDate, Mode=TwoWay,
         RelativeSource={RelativeSource AncestorType={x:Type Window}}}
于 2013-01-30T17:14:14.223 回答