如何在不使用WPF/MVVM中的依赖项解析器的情况下初始化嵌套的View(和ViewModel)

tet*_*ete 6 wpf mvvm

我正在按照MVVM模式设计一个WPF应用程序.在一个UserControl(实际上这种情况多次发生),因为它非常复杂,例如TabControl,我想将它们分成几个子UserControl.例如,在"主"视图中,我们称之为MainUC,我有一个TabControl,它有两个TabItem.由于两者TabItem实际上都包含许多UI元素,我设计了两个UserControl,SubUCA和SubUCB,因此MainUC的XAML如下所示:

<TabControl Name="mainUC" Grid.Row="0" >   
    <TabItem Header="Sub UC A" Name="SubUC1">
        <local:SubUCA />
    </TabItem>
    <TabItem Header="Sub UC B" Name="SubUC2">
        <local:SubUCB />
    </TabItem>
</TabControl > 
Run Code Online (Sandbox Code Playgroud)

但现在我的问题是:我应该如何为这些安排ViewModel UserControl?我目前使用的一种方法是只有一个ViewModel类(称为MainUC_VM),而DataContextMainUC设置为此类实例(注意我没有使用依赖注入,所以我只是在代码隐藏中创建一个实例of MainUC).但是就这样,MainUC_VM类会变得非常复杂,就像MainUC一样.所以我也想把ViewModel分成几个类.例如,在MainUC_VM类中,我可以拥有这样的属性

public SubUCA_VM SubVM1 { get; set; }
public SubUCB_VM SubVM2 { get; set; }
Run Code Online (Sandbox Code Playgroud)

但是,由于我没有使用依赖注入(因为我们的团队还没决定使用它),我如何才能使DataContextSubVM1和SubVM2分别成为SubUC1和SubUC2?我无法在SubUCA和SubUCB的代码隐藏中实例化一个,因为它们与MainUC_VM中的属性成员不同.

我能想到的一些方法是,1)使SubUCA_VM和SubUCB_VM类单例(这类似于依赖注入的相同行为,例如默认使用MEF),或2)使用EvengAggregator来通知对象的实例化.但在我看来,无论哪种方式似乎都会增加不必要的复杂性.为了使用MVVM,这是否意味着依赖注入几乎是必须的?有没有办法在不使用DI的情况下实现它?

Eli*_*bel 4

您可以使用隐式数据模板将数据 (VM) 链接到视图。首先,在资源字典中定义可供您的MainUC. 这可以在用户控件本身中,甚至可以在应用程序资源中。这些数据模板指示 WPF 在需要呈现某种类型的数据时使用哪些控件。

<UserControl.Resources>
    <DataTemplate TargetType="{x:Type local:SubUCA_VM}">
       <local:SubUCA />
    </DataTemplate>
    <DataTemplate TargetType="{x:Type local:SubUCB_VM}">
       <local:SubUCB />
    </DataTemplate>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

然后将选项卡的内容绑定到子虚拟机:

<TabControl Name="mainUC" Grid.Row="0" >   
    <TabItem Header="Sub UC A" Content="{Binding SubVM1}" />
    <TabItem Header="Sub UC B" Content="{Binding SubVM2}" />
</TabControl>
Run Code Online (Sandbox Code Playgroud)

或者,您可以在主虚拟机中拥有子虚拟机列表。每个子虚拟机都应该有一个Title属性,以便选项卡控件可以将其用作标题。这样主虚拟机就可以动态构建 UI。您仍然需要上面定义的数据模板。

<TabControl ItemsSource="{Binding Children}" DisplayMemberPath="Title" />
Run Code Online (Sandbox Code Playgroud)