Как использовать DataTemplateSelector с ContentControl для отображения различных элементов управления на основе модели представления? - PullRequest
0 голосов
/ 09 ноября 2018

Я хочу создать простое окно, которое будет отображать различные элементы управления (SpinEdit или TextEdit) в зависимости от выбранной модели представления.

У меня уже есть код и логика, уже стоящая за нимостается только элемент управления (SpinEdit или TextEdit).

XAML:

   <dx:DXWindow.Resources>

      <DataTemplate x:Key="DataTemplate_Value">
         <dxe:SpinEdit Height="23" MinWidth="200" Width="Auto"
                       Text="{Binding Path=Value, Mode=TwoWay}"
                       Mask="{Binding Mask, Mode=OneWay}" 
                       MaxLength="{Binding Path=InputLength}" />

      </DataTemplate>

      <DataTemplate x:Key="DataTemplate_Text">
         <dxe:TextEdit Height="23" MinWidth="200" Width="Auto"
                       Text="{Binding Path=Value, Mode=TwoWay}"
                       MaskType="RegEx" Mask="{Binding Mask, Mode=OneWay}"
                       MaxLength="{Binding Path=InputLength}"/>
      </DataTemplate>

      <local:PropertyDataTemplateSelector  x:Key="templateSelector"
         DataTemplate_Value="{StaticResource DataTemplate_Value}"
         DataTemplate_Text="{StaticResource DataTemplate_Text}" />

   </dx:DXWindow.Resources>



  <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" />
      </Grid.RowDefinitions>

      <StackPanel Grid.Row="0" >
         <Label x:Uid="Label" MinHeight="24" MinWidth="60" Content="Value" />
         <ContentControl ContentTemplateSelector="{StaticResource templateSelector}" />
      </StackPanel>

      <StackPanel Grid.Row="1" x:Uid="OKCancel_Buttons" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom">
         <Button Height="23" x:Name="OK_Button" Click="OK_Click" Content="OK" IsDefault="True" HorizontalAlignment="Right" MinWidth="95" />
         <Button Height="23" x:Name="Cancel_Button" Click="Cancel_Click" Content="Cancel" HorizontalAlignment="Right" MinWidth="95" />
      </StackPanel>

Где в <ContentControl> я хочу выбрать, какой элемент управления будетотображается (SpinEdit для чисел и TextEdit для имен / букв)

C #:

   public class PropertyDataTemplateSelector : DataTemplateSelector
   {
      public DataTemplate DataTemplate_Value { get; set; }
      public DataTemplate DataTemplate_Text { get; set; }

      public override DataTemplate SelectTemplate(object item, DependencyObject container)
      {
         var selector = item as TInputBaseVM;

         if(selector is TInputValueVM)
            return DataTemplate_Value;
         return DataTemplate_Text;
      }
   }

Где я хочу вернуть конкретный DataTemplate на основе модели представления, котораясоздается в коде c ++ / cli.

C ++ / cli:

  TInputValueVM ^oExchange_Value;
  TInputTextVM ^oExchange_Text;

  int inputFormat = A_Attributes.GetInputFormat();

  if(inputFormat)
     oExchange_Text = gcnew TInputTextVM(gcnew System::String(A_Attributes.GetTitle()), gcnew System::String(A_Attributes.GetMask()),
        A_Attributes.GetInputLength(), gcnew System::String(A_Attributes.GetInitialText()));
  else
     oExchange_Value = gcnew TInputValueVM(gcnew System::String(A_Attributes.GetTitle()), gcnew System::String(A_Attributes.GetMask()),
        A_Attributes.GetInputLength(), A_Attributes.GetInitialValue());

  Dialogs::TSignalNumberPositionDialog^ dialog = gcnew Dialogs::TSignalNumberPositionDialog();

  if(inputFormat)
     dialog->DataContext = oExchange_Text;
  else
     dialog->DataContext = oExchange_Value;

  dialog->ShowDialog();

Дело в том, что значение item в переопределенной функции выбора всегда имеет значение null, и я понятия не имею, как его связать вXAML, так как все примеры, которые мне удалось найти, это ListBox es и т. Д. Нет примера того, как отображать различные элементы управления в зависимости от модели представления.

EDIT:

Как было предложено, я добавил свойство Content в ContentControl и передал ему аргумент, который теперь является аргументом 'item' в селекторе.Работает просто отлично!

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Вам не нужен DataTemplateSelector. WPF предоставляет механизм, который автоматически выбирает DataTemplate для ContentTemplate ContentControl в соответствии с типом Content.

Как описано в Шаблон данных. Тип данных :

Когда вы задаете для этого свойства тип данных без указания ключа x: ключ, DataTemplate автоматически применяется к объектам данных этого типа.

Итак, отбросьте значение x:Key и ваш DataTemplateSelector, установите DataType

<dx:DXWindow.Resources>
    <DataTemplate DataType="{x:Type local:TInputValueVM}">
        <dxe:SpinEdit Height="23" MinWidth="200" Width="Auto"
                      Text="{Binding Path=Value, Mode=TwoWay}"
                      Mask="{Binding Mask, Mode=OneWay}" 
                      MaxLength="{Binding Path=InputLength}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:TInputTextVM}">
        <dxe:TextEdit Height="23" MinWidth="200" Width="Auto"
                      Text="{Binding Path=Value, Mode=TwoWay}"
                      MaskType="RegEx" Mask="{Binding Mask, Mode=OneWay}"
                      MaxLength="{Binding Path=InputLength}"/>
    </DataTemplate>
</dx:DXWindow.Resources>

и связать ContentControl Content со свойством, которое возвращает либо TInputValueVM, либо TInputTextVM:

<ContentControl Content="{Binding InputVM}" />

Соответствующий шаблон данных теперь будет выбран автоматически.

0 голосов
/ 09 ноября 2018

Вы должны добавить некоторое значение в Content свойство ContentControl. Это значение будет передано SelectTemplate как object item. Вам, вероятно, следует привязать к нему какое-либо свойство в ViewModel, чтобы иметь возможность изменить его оттуда.

...