如何实现“传递”DataBinding?

时间:2009-04-15 23:23:15

标签: wpf dependency-properties

一点背景:我从数据库加载WPF UI,该数据库存储在属性表(控件类型,标签,边距等)中,我将其加载到我调用的类中ControlPresenter。基本上我将ControlPresenter设置为ContentPresenter的DataContext,并使用TemplateSelector选择要加载的控件类型。 DataTemplate将其属性从ControlPresenter公开的DependencyProperties中加载。

这一切都非常有效。当我尝试将数据(例如TextBox的Text属性与演示者的Name属性)绑定到这些控件的其他演示者(具有实现INotifyPropertyChanged的常规属性)时,我遇到的问题就出现了。控件的DataContext是关联的ControlPresenter,因此我无法直接绑定到其他演示者,我无法在同一依赖项属性上设置两个绑定(我无法将控件和所需的演示者属性绑定到同一个DP) 。

可能的解决方案:

  1. 我可以将所有其他演示者转换为使用DP(非常耗时且容易导致继承问题)
  2. 我可以为我想要传递的每个属性使用两个DP,并尝试通过更改的通知将它们绑定在一起
  3. 这两个似乎都有问题,容易破裂,所以我希望别人能提出更好的解决方案。

    编辑:我想出了一个效果相当不错的解决方案(见下文)。感谢所有看过这个的人,如果你想出一个比我更好的方法,请告诉我。

2 个答案:

答案 0 :(得分:0)

有多种方法可以访问范围DataContexts。

1)ElementName Binding

这可能是最不实用的,因为在大多数现实世界的场景中,你想要绑定的东西无论如何都不在。但只要框架元素在名称范围内,它就是访问并行或父数据上下文的一种方式。

<TextBox Text="{Binding ElementName=ControlSomewhereElseBoundToSomeOtherControlPresenter, Path=DataContext.SomeTextPropertyOnTheControlPresenter}" />

2)RelativeSource Binding

这类似于#1,但使用RelativeSource导航到适当的可视元素并获取DataContext。当然,这假设您尝试获取的DataContext是您当前在Visual Tree中的位置。

3)使用静态继电器

您可以在静态类中公开替代ControlPresenters,该静态类充当ViewModel的外观。然后,在每个ViewModel构造实例属性中传递给静态方法/属性。这是跨多个View模型实现共享存储的常用方法。我意识到这种技术需要你稍微改变你的模式,但在这些“ControlPresenter”类中添加一个简单的ViewModel包装似乎比你描述的选项简单得多。

答案 1 :(得分:0)

我最终通过将Binding.Source设置为所需的ViewModel然后在数据库中使用Binding.Path的路径来设置代码中的绑定。我将绑定存储在Dictionary(Of DependencyProperty,BindingBase)中,当Control加载时,我使用BindingOperations.SetBinding来设置控件上的绑定。这似乎很有效,除了偶尔的操作顺序问题(例如,如果在ItemsSource之前设置SelectedItem / SelectedValue,它将被设置但不会显示在ComboBox中)。