如何使用 DataTemplateSelector 和 ContentControl 根据视图模型显示不同的控件? [英] How to use DataTemplateSelector with ContentControl to display different controls based on the view-model?

查看:22
本文介绍了如何使用 DataTemplateSelector 和 ContentControl 根据视图模型显示不同的控件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个简单的窗口,根据选择的视图模型显示不同的控件(SpinEditTextEdit).

I want to create a simple window that would display different controls (SpinEdit or TextEdit) based on the view-model that is selected.

我已经完成了它背后的代码和逻辑,剩下的就是显示控件(SpinEditTextEdit)本身.

I have the code and logic behind it done already, what is left is displaying the control (SpinEdit or TextEdit) itself.

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>

我想选择将显示哪个控件(SpinEdit 用于数字,TextEdit 用于名称/字母)

Where in the <ContentControl> I want to select which control will be displayed (SpinEdit for numbers and TextEdit for names/letters)

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

我想根据在 c++/cli 代码中创建的视图模型返回特定 DataTemplate 的位置.

Where I want to return a specific DataTemplate based on the view-model that is created in the c++/cli code.

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 中绑定它,因为所有示例我到目前为止已经找到了 ListBoxes 等.没有关于如何基于视图模型显示不同控件的示例.

The point is, the item value in the overriden selector function always has the null value and I have no idea how to bind it in XAML since all the examples I've managed to find so far are ListBoxes etc. There's no example on how to display different controls based on the view-model.

按照建议,我在 ContentControl 中添加了 Content 属性,并向它传递了一个参数,该参数现在是选择器中的item"参数.效果很好!

As suggested, I added Content property in the ContentControl and passed it an argument which is now the 'item' argument in the selector. Works just fine!

推荐答案

您不需要 DataTemplateSelector.WPF 提供了一种机制,可以根据 Content 的类型自动为 ContentControl 的 ContentTemplate 选择 DataTemplate.

You do not need a DataTemplateSelector. WPF provides a mechanism that automatically selects a DataTemplate for the ContentTemplate of a ContentControl according to the type of a Content.

数据模板.数据类型:

当您将此属性设置为未指定 x:Key 的数据类型时,DataTemplate 将自动应用于该类型的数据对象.

When you set this property to the data type without specifying an x:Key, the DataTemplate gets applied automatically to data objects of that type.

因此删除 x:Key 值和您的 DataTemplateSelector,设置 DataType

So drop the x:Key value and your DataTemplateSelector, set 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 的内容绑定到返回 TInputValueVM 或 TInputTextVM 的属性:

and bind the ContentControl's Content to a property that returns either a TInputValueVM or a TInputTextVM:

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

现在将自动选择适当的数据模板.

The appropriate DataTemplate will now be selected automatically.

这篇关于如何使用 DataTemplateSelector 和 ContentControl 根据视图模型显示不同的控件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆