从XAML强制ViewModel实例化

时间:2018-11-14 14:35:10

标签: c# wpf mvvm

我有一个视图OutputOptionsView,其中包含几个UserControls,其选项设置根据组合框的选择而显示。

我在Datacontext中为Datatemplates创建UserControlsOutputOptionsView,像这样:

<UserControl.Resources>
    <ResourceDictionary>
        <local:OutputOptionsViewModel x:Key="vm" />

        <DataTemplate x:Key="OptionSettings1" DataType="{x:Type views:OptionSettings1View}">
            <views:OptionSettings1View />
        </DataTemplate>

        <DataTemplate x:Key="OptionSettings2" DataType="{x:Type views:OptionSettings2View}">
            <views:OptionSettings2View />
        </DataTemplate>

        ....
    </ResourceDictionary>
</UserControl.Resources>

OptionSettingsViews的显示按以下方式处理:

        <ContentControl Name="OutputOptionsContentControl" Content="{Binding}" >
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Setter Property="ContentTemplate" Value="{StaticResource OptionSettings1}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding AvailableOptionsListSelectedIndex}" Value="1">
                            <Setter Property="ContentTemplate" Value="{StaticResource OptionSettings2}" />
                        </DataTrigger>
                        ...
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
ComboBox的

ItemsSourceSelectedIndex绑定到OutputOptionsViewModel的视图模型类OutputOptionsView

<ComboBox Name="AvailableOptionsListComboBox" ItemsSource="{Binding AvailableOptionsList}" DisplayMemberPath="OptionTitle" 
                  SelectedIndex="{Binding AvailableOptionsListSelectedIndex, UpdateSourceTrigger=PropertyChanged}"/>

我的OptionSettings视图中的每个视图都还具有一个ViewModel:

<UserControl.Resources>
    <ResourceDictionary>
        <local:OptionSettings1ViewModel x:Key="vm" />
    </ResourceDictionary>
</UserControl.Resources>

<Grid DataContext="{StaticResource vm}">
...
</Grid>

现在,我的问题涉及组合框的人口。我创建了一个接口,其中包含每个OptionsSettingsViewModels继承的OptionTitle。组合框的AvailableOptionsList的{​​{1}}是此接口的列表。

ItemsSouce

它将在public List<IOutputOption> AvailableOptionsList { get; set; } 类的构造方法中实例化。

在每个OutputOptionsViewModel类构造函数中,我将各自的OptionSettingsViewModel添加到此列表中:

OptionsSettingsViewModel

这将导致以下问题:只要没有实例化OptionSettingsViews,就不会填充组合框,但是由于无法从空组合框中选择它们,因此无法实例化它们。 因此,我希望强制OptionSettingsViews的实例化。

1 个答案:

答案 0 :(得分:1)

这些评论让我觉得,有一些基本的误解:

  

[Lynn Crumbling]我将完全重新设计它,以便始终实例化所有视图模型,并将它们嵌套在mainviewmodel下。您将需要它们,为什么不直接将它们放在主vm的ctor中呢?

  

[Roland Deschain]实际上是我目前解决的方法,但是这意味着我必须在每个optionssettingsviewmodel的代码背后设置数据上下文,这是我想避免的

因此,正如Lynn所说,您应该首先在主视图模型中注册子视图模型,此时无需任何视图参与。

然后,您可以为视图模型定义DataTemplate,而不是像现在一样为视图定义。

<DataTemplate DataType="{x:Type viewmodels:OptionSettings1ViewModel}">
    <views:OptionSettings1View />
</DataTemplate>

<DataTemplate DataType="{x:Type viewmodels:OptionSettings2ViewModel}">
    <views:OptionSettings2View />
</DataTemplate>

通过删除x:Key并将DataType更改为viewmodel类型,将自动选择模板以显示相应类型的内容。

子视图的DataContext将自动从外部设置。不要在xaml控件中实例化子视图模型。

在您的主OutputOptionsViewModel中,您应该托管子视图模型的集合。在组合框中,您应该直接将此集合用作itemssource。

然后只需删除所有复杂的模板选择xaml并将内容直接绑定到您选择的子视图模型:

<ContentControl
    Name="OutputOptionsContentControl"
    Content="{Binding ElementName=AvailableOptionsListComboBox,Path=SelectedItem}" />