使用MVVM从ViewModel的窗口资源中选择DataTemplate

时间:2018-10-01 17:53:05

标签: c# wpf mvvm datatemplate

我有一个视图,在窗口的一小部分显示用户单击的项目的详细信息。这些细节的格式发生了变化,因此我的原始实现对不同种类的商品具有隐藏/显示逻辑:

<Grid Name="Details1" Visibility="Collapsed">
    <TextBox Name="Details_Field1" />
</Grid>
<Grid Name="Details2" Visibility="Visible">
    <TextBox Name="Details_Field2" />
    <TextBox Name="Details_Field3" />
</Grid>
<Grid Name="Details3" Visibility="Collapsed">
    <TextBox Name="Details_Field4" />
    <TextBox Name="Details_Field5" />
    <DataGrid Name="Details_DataGrid1 />
</Grid>

现在,我要使这个“更糟”。我的策略是使每个网格都具有自己的DataTemplate,并按以下方式管理状态:

查看:

<Window.Resource>
    <DataTemplate x:Key="Details_Template1>
        <Grid Name="Details1">
            <TextBox Name="Details_Field1" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="Details_Template2>
        <Grid Name="Details2">
            <TextBox Name="Details_Field2" />
            <TextBox Name="Details_Field3" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="Details_Template3>
        <Grid Name="Details3">
            <TextBox Name="Details_Field4" />
            <TextBox Name="Details_Field5" />
            <DataGrid Name="Details_DataGrid1 />
        </Grid>
    </DataTemplate>
</Window.Resources>

....

<Grid Name="DetailsGoHere">
    <ContentControl ContentTemplate="{Binding DetailsDisplay}" />
</Grid>

ViewModel:

    private DataTemplate _detailsDisplay;
    public DataTemplate DetailsDisplay
    {
        get => _detailsDisplay;
        private set => RaisePropertyChangedEvent(ref _detailsDisplay, value);
    }

....

private void Item_OnClick()
{
    // Pseudocode!  How do I reference Details_Template1 as a resource?
    DetailsDisplay = MyView.Details_Template1;
}

正如评论所暗示的,我不确定如何从ViewModel的Window.Resource块中引用DataTemplates,所以我的问题是双重的:

1:这是解决此类问题的好方法吗?

2:如果是这样,如何在ViewModel中引用Window.Resource块中的项目?

1 个答案:

答案 0 :(得分:0)

DataTemplateSelector用于在WPF中切换DataTemplate。

请具体参考此链接http://www.wpftutorial.net/datatemplates.html

PropertyDataTemplateSelector-

public class PropertyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultnDataTemplate { get; set; }
public DataTemplate BooleanDataTemplate { get; set; }
public DataTemplate EnumDataTemplate { get; set; }

public override DataTemplate SelectTemplate(object item, 
           DependencyObject container)
{
    DependencyPropertyInfo dpi = item as DependencyPropertyInfo;
    if (dpi.PropertyType == typeof(bool))
    {
        return BooleanDataTemplate;
    }
    if (dpi.PropertyType.IsEnum)
    {
        return EnumDataTemplate;
    }

    return DefaultnDataTemplate;
   }
}

查看-

<Window x:Class="DataTemplates.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:DataTemplates"
xmlns:sys="clr-namespace:System;assembly=mscorlib">

<Window.Resources>

    <!-- Default DataTemplate -->
    <DataTemplate x:Key="DefaultDataTemplate">
       ...
    </DataTemplate>

    <!-- DataTemplate for Booleans -->
    <DataTemplate x:Key="BooleanDataTemplate">
       ...
    </DataTemplate>

    <!-- DataTemplate for Enums -->
    <DataTemplate x:Key="EnumDataTemplate">
        ...
    </DataTemplate>

    <!-- DataTemplate Selector -->
    <l:PropertyDataTemplateSelector x:Key="templateSelector"
          DefaultnDataTemplate="{StaticResource DefaultDataTemplate}"
          BooleanDataTemplate="{StaticResource BooleanDataTemplate}" 
          EnumDataTemplate="{StaticResource EnumDataTemplate}"/>
</Window.Resources>
<Grid>
    <ListBox ItemsSource="{Binding}" Grid.IsSharedSizeScope="True" 
             HorizontalContentAlignment="Stretch" 
             ItemTemplateSelector="{StaticResource templateSelector}"/>
</Grid>