c# - 从 XAML 强制 ViewModel 实例化
问题描述
我有一个视图OutputOptionsView
,其中包含多个UserControls
选项设置,这些设置取决于组合框的选择。
我像这样为内部创建Datacontext
and :Datatemplates
UserControls
OutputOptionsView
<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>
ItemsSource
和SelectedIndex
ComboBox 绑定到 viewmodelOutputOptionsViewModel
类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>
现在我的问题涉及组合框的人口。我创建了一个接口,其中包含每个都继承的 OptionTitle OptionsSettingsViewModels
。AvailableOptionsList
组合ItemsSouce
框是此接口的列表。
public List<IOutputOption> AvailableOptionsList { get; set; }
它将在OutputOptionsViewModel
类的构造函数中实例化。
在每个OptionSettingsViewModel
类构造函数中,我将各自添加OptionsSettingsViewModel
到此列表中:
public OptionSettings1ViewModel()
{
OutputOptionsViewModel.AvailableOptionsList.Add(this);
}
这会导致以下问题:只要 OptionSettingsViews 没有被实例化,组合框就不会被填充,但是它们不能被实例化,因为它们不能从空的组合框中被选择。因此,我希望强制实例化 OptionSettingsViews。
解决方案
评论让我觉得,有一些基本的误解:
[Lynn Crumbling] 我会完全重新架构它以始终实例化所有视图模型,将它们嵌套在主视图模型下。您将需要它们,那么为什么不直接在主 vm 的 ctor 中启动它们呢?
和
[Roland Deschain] 这实际上是我目前解决它的方法,但这意味着我必须在每个选项设置视图模型的代码隐藏中设置数据上下文,这是我想尽可能避免的
因此,正如 Lynn 所说,您应该首先在主视图模型中注册子视图模型,此时不需要任何视图参与。
然后您可以DataTemplate
为viewmodels定义,而不是像现在这样为视图定义。
<DataTemplate DataType="{x:Type viewmodels:OptionSettings1ViewModel}">
<views:OptionSettings1View />
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:OptionSettings2ViewModel}">
<views:OptionSettings2View />
</DataTemplate>
通过删除x:Key
并将 更改DataType
为 viewmodel 类型,将自动选择模板以显示相应类型的内容。
您的子视图的 DataContext 将从外部自动设置。不要在控件 xaml 中实例化子视图模型。
在您的 mainOutputOptionsViewModel
中,您应该托管子视图模型的集合。在您的组合框中,您应该直接将此集合用作 itemssource。
然后只需删除所有复杂的模板选择 xaml 并将内容直接绑定到您选择的子视图模型:
<ContentControl
Name="OutputOptionsContentControl"
Content="{Binding ElementName=AvailableOptionsListComboBox,Path=SelectedItem}" />
推荐阅读
- .net - 如何在 VB.NET 中获取出站 Twilio 调用的最终状态?
- vue.js - v-tooltip 不显示其背后的组件
- clips - CLIPS:检查多个事实
- asp.net-core - 无法使用身份服务器访问客户端应用程序
- angular - 反应式表单 - 控件无效但表单仍然有效
- php - 如何将 cURL 转换为 PHP cURL
- mysql - mysql bash shell脚本输出错误
- javascript - 为什么 onclick 事件在触摸屏上不起作用,而在桌面上起作用?
- cluster-analysis - 从一组文档中提取重要的子部分以及与它们相关联的子文档集
- ionic-framework - menuClose 没有关闭我的左侧菜单