基于 SelectedItem 的 WPF DataTemplate、TemplateSelectors、ContentPresenter

WPF DataTemplate, TemplateSelectors, ContentPresenter based on SelectedItem

我很困惑使用什么以及如何开始实施,但我想要基于枚举 属性 当更改某个网格时应该显示。

目前我有大约 20 个网格,在 属性 更改时使用可见性。 这对于两件事来说并不理想。所有 20 个网格将从启动时绑定,这对性能不利。其次,某些 "Grids" 对于枚举 属性 的某些值是相同的。所以我在一些网格中有重复的代码。

现在我有一个枚举:

   public enum MyEnumsForDropDown
    {
        Enum1= 1,
        Enum2= 2,
        Enum3= 3,
        Enum4= 4,
        Enum5= 5
    }

我绑定到的 ViewModel 中的我的对象用于:

Public class MyObject
{
  private Enums.MyEnumsForDropDown _myChosenEnum;
  public Enums.MyEnumsForDropDown MyChosenEnum
  {
    get { return _myChosenEnum; }
    set
    {
      _myChosenEnum = value;
      this.NotifyPropertyChanged( x => x.MyChosenEnum );
    }
  }
}

我的XAML:

<ComboBox ItemsSource="{Binding CollectionOfEnums}" 
DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding 
MyObject.MyChosenEnum}"></ComboBox>

<Grid Grid.Row="1" Grid.Column="3" Visibility="{Binding 
Path=MyObject.MyChoseEnum, Converter={StaticResource 
EnumToVisibleCollapseConverter}, ConverterParameter={x:Static 
myenumsNameSpace:Enums+MyEnumsForDropDown.Enum1}}">
  <TextBlock Content"This Grid displays when Enum1 is chosen"/>
</Grid>

<Grid Grid.Row="1" Grid.Column="3" Visibility="{Binding 
Path=MyObject.MyChoseEnum, Converter={StaticResource 
EnumToVisibleCollapseConverter}, ConverterParameter={x:Static 
myenumsNameSpace:Enums+MyEnumsForDropDown.Enum2}}">
  <TextBlock Content"This Grid displays when Enum2 is chosen"/>
</Grid>

如何更改网格以某种方式像 ContentPresenters 或 DataTemplates 或任何我需要使用的东西取决于我的对象中的 属性 MyChosenEnum 何时更改?

您可以为每个枚举值定义一个 DataTemplate,然后使用 ContentControlStyle 来显示正确的值:

<ContentControl Content="{Binding MyObject.MyChosenEnum}">
    <ContentControl.Resources>
        <DataTemplate x:Key="Enum1">
            <Grid />
        </DataTemplate>
        <DataTemplate x:Key="Enum2">
            <Grid />
        </DataTemplate>
    </ContentControl.Resources>
    <ContentControl.Style>
        <Style TargetType="ContentControl">
            <Style.Triggers>
                <DataTrigger Binding="{Binding MyObject.MyChosenEnum}"
                             Value="{x:Static myenumsNameSpace:Enums+MyEnumsForDropDown.Enum1}">
                    <Setter Property="ContentTemplate" Value="{StaticResource Enum1}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding MyObject.MyChosenEnum}"
                             Value="{x:Static myenumsNameSpace:Enums+MyEnumsForDropDown.Enum2}">
                    <Setter Property="ContentTemplate" Value="{StaticResource Enum2}" />
                </DataTrigger>
                <!-- and so on for each enum value -->
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

或者您可以使用 DataTemplateSelector:

public class YourSelector : DataTemplateSelector
{
    public DataTemplate Enum1 { get; set; }
    public DataTemplate Enum2 { get; set; }
    //...

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        MyEnumsForDropDown value = (MyEnumsForDropDown)item;
        switch(value)
        {
            case MyEnumsForDropDown.Enum1:
                return Enum1;
            case MyEnumsForDropDown.Enum2:
                return Enum2;
        }

        return base.SelectTemplate(item, container);
    }
}

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="Enum1">
            <Grid />
        </DataTemplate>
        <DataTemplate x:Key="Enum2">
            <Grid />
        </DataTemplate>
        <local:YourSelector x:Key="selector" Enum1="{StaticResource Enum1}" Enum2="{StaticResource Enum2}" />
    </Grid.Resources>
    <ContentControl Content="{Binding MyObject.MyChosenEnum}"
                    ContentTemplateSelector="{StaticResource selector}" />
</Grid>