将父视图 DataContext 绑定到 DataTemplate 子视图 DataContext

Binding Parent View DataContext to DataTemplate Child View DataContexts

我最近一直在试验 WPF、Xaml、MVVM 和 DependencyInjection。因此,我正在使用 MVVM 原则创建 UI。 UI 的某个部分被设计成一个向导,其中并非所有可用选项都同时呈现给用户。选项的每个部分都是它自己的视图(子视图),单个视图(父视图)在 ContentControl 中托管这些子视图。用户设置某些选项并使用按钮从一个部分移动到另一个部分。

查看导航

为了在这些视图之间切换,我使用了 DataTemplateSelector,每个子视图在我的 Xaml 资源中定义为 DataTemplate。

主视图中的内容控件:

        <ContentControl Content="{Binding ElementName=ParentViewControl, Path=ViewState, Mode=TwoWay}"
                    ContentTemplateSelector="{StaticResource MyTemplateSelector}" />

示例子视图数据模板:

    <DataTemplate x:Key="SubViewATemplate">
        <local:SubViewAView x:Name="SVAView" DataContext="{Binding ElementName=ParentViewControl, Path=DataContext}" ViewState="{Binding ElementName=ParentViewControl, Path=ViewState, Mode=TwoWay }" />
    </DataTemplate>

在父视图和每个子视图上,我创建了一个名为 ViewState(枚举)的依赖项 属性。它们通过数据模板相互绑定。在每个视图的代码隐藏中,我根据用户输入更新此 ViewState 属性,并将其传播到父视图,父视图又触发 DataTemplateSelector。到目前为止,一切都很好。导航效果很好。

视图模型信息

父视图有一个 ViewModel,它实现了 INotify属性Changed 作为它的 DataContext。我正在尝试使用这个单一的 ViewModel 将属性绑定到父视图和子视图。问题是上面 DataTemplate 片段中的 DataContext 绑定不起作用。 (这对我来说很奇怪,因为 ViewState 绑定确实如此。)经过各种尝试使其工作后,子视图上的 DataContext 为 null 或 ViewState 控制变量。

我目前正在使用 UnityContainer 作为我的依赖注入器。

各种尝试

以下是我尝试过但都失败的各种其他方法:

1) 将 ViewModel 注册为 UnityContainer 中的单例,从而在子视图上使用构造函数注入来设置 DataContext。 (不起作用,因为 DataTemplate 资源必须有一个无参数构造函数。)

2) 在UnityContainer 中将ViewModel 注册为单例,然后在子View 上使用属性 注入来设置DataContext。 (不起作用。我认为这是由于在 Xaml 中实例化对象时 UnityContainer 不起作用。)

3) 为每个需要 ViewModel 的子视图创建子 ViewModel,以显示本应存在于父 ViewModel 上的属性。我之前用它来解决 UnityContainer 的 Xaml 实例化问题。然后,我将 DataTemplate 中的 DataContext 绑定替换为关联的子 ViewModel。 (不起作用,因为出于某种原因,我的父视图的 DataContext 被设置为 ViewState 变量,而不是保留我在视图的构造函数中设置的 ViewModel。这反过来意味着子 ViewModel 属性找不到我的父 ViewModel 绑定到子视图的 DataContext。) UserControls 的 Content 和 DataContext 是一回事吗?设置一个会影响另一个吗?

4) 将 ViewState 依赖项 属性 从 View 移动到 ViewModel,然后设置 ContentControl 的 Content 以绑定到 ViewModel。这违反了 MVVM 原则,但此时我正在尽一切努力让它发挥作用。 (它不起作用,因为在视图的代码隐藏中更改 ViewState 时,ViewModel 不会按更改触发。)我没有进一步讨论这个,因为我不想更深入地违反 MVVM。

结论

在过去的几天里,我在这个网站上找到了大部分尝试解决方案。我没有接受过 WPF、Xaml 和 MVVM 方面的任何正式培训,所以我怀疑我遗漏了一些明显的东西,或者正在尝试做一些不可能的事情。我将继续尝试对上述内容进行变体并进行研究,直到找到可行的方法,但我想我会利用这里的集体知识来帮助我找到解决方案。

我更喜欢让这组视图使用单个 ViewModel 作为它们的 DataContext,这样我就可以将属性绑定到它们的控件。并让视图的导航由 DataTemplateSelector 控制。有没有我没有看到的方法来做到这一点?

感谢您的宝贵时间!

我以前遇到过类似的问题,我使用 RelativeSource 绑定时运气不错。也许尝试这样的事情:

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=DataContext}"

只是一个想法。