Выбор DataTemplate из оконного ресурса в ViewModel с MVVM - PullRequest
0 голосов
/ 01 октября 2018

У меня есть вид, в котором небольшая часть окна отображает детали элемента, на который пользователь нажимает.Формат этих деталей меняется, поэтому в моей первоначальной реализации была логика скрытия / показа для различных типов элементов:

<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 и управлять состоянием следующим образом:

View:

<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;
}

Как следует из комментария, я не уверен, как ссылаться на DataTemplates в моем блоке Window.Resource из моей ViewModel, поэтому мой вопрос состоит из двух частей:

1: Является ли это хорошим решением проблемы такого рода?

2: Если да, то как мне ссылаться на элемент из моего блока Window.Resource в моей ViewModel?

1 Ответ

0 голосов
/ 01 октября 2018

DataTemplateSelector используются для переключения DataTemplate в WPF.

Пожалуйста, обратитесь к этой ссылке 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>

...