【问题标题】:How can I implement a "pass-through" DataBinding?如何实现“直通”数据绑定?
【发布时间】:2009-04-15 23:23:15
【问题描述】:

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

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

可能的解决方案:

  1. 我可以将所有其他演示者转换为使用 DP(非常耗时且容易导致继承问题)
  2. 我可以为我想要通过的每个属性使用两个 DP,并尝试通过更改的通知将它们绑定在一起

这两个似乎都存在问题并且容易崩溃,所以我希望其他人提出了更好的解决方案。

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

【问题讨论】:

    标签: wpf dependency-properties


    【解决方案1】:

    有几种方法可以访问超出范围的 DataContexts。

    1) 元素名绑定

    这可能是最没用的,因为在大多数现实世界的场景中,您尝试绑定的内容无论如何都超出了名称范围。但只要框架元素在名称范围内,它就是一种访问并行或父数据上下文的方法。

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

    2) 相对源绑定

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

    3) 使用静态中继

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2023-03-11
        • 2023-04-01
        • 1970-01-01
        • 2017-05-22
        • 2010-09-28
        • 2013-05-05
        • 1970-01-01
        • 2011-03-21
        相关资源
        最近更新 更多