2009-04-15 48 views
0

小背景:我从一个数据库中加载一个WPF UI,该数据库存储在一个属性表(控制类型,标签,边距等)中,我加载到一个类中,我调用了ControlPresenter。基本上,我将ControlPresenter设置为ContentPresenter的DataContext,并使用TemplateSelector来选择要加载的控件类型。 DataTemplate(s)将它们的属性加载到ControlPresenter公开的DependencyProperties之外。如何实现“传递”DataBinding?

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

可能的解决方案:

  1. 我可以转换所有其他主持人的使用移民(非常耗时而且容易导致与继承问题)
  2. 我就可以使用两个检测点为每个属性我想要通过并尝试通过更改通知将它们绑定在一起

这两个看起来有问题并且容易打破,所以我希望别人提出了更好的s olution。

编辑:我想出了一个相当不错的解决方案(见下文)。感谢大家看到这个,如果你想出一个比我更好的方法,请让我知道。

回答

0

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

0

有几种访问作用域DataContexts的方法。

1)的ElementName绑定

这可能是最有用的,在最真实世界的场景,你正在试图绑定到超出名称范围的反正。但只要框架元素位于名称范围内,它就是访问并行或父级数据上下文的一种方式。

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

2)的RelativeSource绑定

这类似于#1,但使用的RelativeSource到导航到相应的视觉元素和抓住的DataContext。当然,这假设您正试图获取的DataContext位于您目前位于Visual Tree中的哪个位置。

3)使用静态继电器

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

+0

嗯,我得看看我是否可以得到选项3号的工作。 – 2009-04-16 13:36:30