如何在DataTemplate中将ComboBox绑定到所有枚举类型?

3
我希望根据绑定类型显示框架UI元素。 对于枚举类型,我想显示ComboBox。
我已经在XAML中有了这部分内容:
<StackPanel Grid.Column="2">
   <StackPanel.Resources>

       <ObjectDataProvider x:Key="EnumValues" ObjectType="{x:Type sys:Enum}" MethodName="GetValues">
            <ObjectDataProvider.MethodParameters>
                 <x:Type TypeName= <-- How to indicate for all enum types? --> >
            </ObjectDataProvider.MethodParameters>
       </ObjectDataProvider>

       <DataTemplate DataType="{x:Type sys:String}">
            <TextBox Text="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentPresenter}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center" BorderThickness="0" />
       </DataTemplate>
       <DataTemplate DataType="{x:Type sys:Double}">
            <TextBox Text="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentPresenter}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center" BorderThickness="0"/>
       </DataTemplate>
       <DataTemplate DataType="{x:Type sys:Enum}">
            <ComboBox ItemsSource="{Binding Source={StaticResource EnumValues}}"  SelectedValue="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentPresenter}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center" BorderThickness="0"/>
       </DataTemplate>

   </StackPanel.Resources>
   <ContentPresenter Content="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</StackPanel>

请问有办法在XAML上实现吗?

更新: 目前,我使用了两个转换器来解决这个问题。 第一个转换器从给定的枚举中返回字符串集合作为ItemsSource:

    /// <summary>
    /// Converts the given value into a collection of strings
    /// </summary>
    /// <returns>collection of strings</returns>
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            IEnumerable<Enum> enumsCollection = value.GetType().GetEnumValues().Cast<Enum>();
            return enumsCollection.Select(enumValue => enumValue.ToString());
        }
        return null;
    }

第二种方法将枚举转换为字符串并实现选定值的相互转换:
public class EnumToStringConverter : IValueConverter
    {
        #region Properties

        /// <summary>
        /// Last target type to be converted
        /// </summary>
        protected Type LastTargetType { get; set; }

        #endregion

        #region IValueConverter Members

        /// <summary>
        /// Converts a given value into a string representation
        /// </summary>
        /// <returns>string</returns>
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null)
            {
                LastTargetType = value.GetType();
                return value.ToString();
            }

            return null;
        }

        /// <summary>
        /// Converts back a given value into an enum representation
        /// </summary>
        /// <returns>enum</returns>
        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return Enum.Parse(LastTargetType, value.ToString());
        }

        #endregion
    }

在XAML中,ComboBox将被定义如下所示:

                                    <DataTemplate DataType="{x:Type sys:Enum}">
                                        <ComboBox Name="EnumComboBox" ItemsSource="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentPresenter}, Converter={StaticResource EnumValuesConv}, Mode=OneTime}"  SelectedValue="{Binding Content, Converter={StaticResource EnumToStringConv}, RelativeSource={RelativeSource AncestorType=ContentPresenter}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Focusable="False" Width="100" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center" BorderThickness="0">
                                            <ComboBox.ItemTemplate>
                                                <DataTemplate>
                                                    <TextBlock Text="{Binding}"/>
                                                </DataTemplate>
                                            </ComboBox.ItemTemplate>
                                        </ComboBox>
                                    </DataTemplate>

我不明白你的问题实际上是什么。 - King King
在“ObjectDataProvider”下面,我应该写什么才能支持所有枚举,而不是特定的枚举?这种方式可行吗? - Yaniv
绝对不可能。即使在C#中,您也必须明确指定类型。 - Rohit Vats
请注意,此解决方案仅适用于一种枚举类型。如果您有多个不同的枚举绑定到此,则 EnumToString.ConvertBack 方法将失败。 - Jezzamon
2个回答

0
你发布的解决方案存在一些问题,它不能很好地处理同时使用不同类型的枚举(即你不能绑定到两个绑定到不同枚举类型的组合框)。通过稍微修改一下它,我得到了一个更简单的解决方案,可以适用于所有情况。
如果你不将枚举值转换为字符串,而是将它们保留为枚举,则可以直接绑定到SelectedValue而无需使用另一个转换器。
xaml如下:
<ComboBox ItemsSource="{Binding Path=Value, Converter={StaticResource EnumValuesConverter}, Mode=OneTime}"
          SelectedValue="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>

这是转换器

public class EnumValuesConverter : IValueConverter
{
    /// <summary>
    /// Converts the given value into a collection of enum values
    /// </summary>
    /// <returns>collection of strings</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            IEnumerable<Enum> enumsCollection = value.GetType().GetEnumValues().Cast<Enum>();
            return enumsCollection;
        }
        return null;
    }

    /// <summary>
    /// Converts back a given value. Not supported for this converter.
    /// </summary>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException("EnumValuesConverter is a OneWay converter.");
    }

}

当然,这里出现的名称将是您在枚举中定义的名称。如果您希望您的名称更加用户友好,请查看http://www.codeproject.com/Articles/29495/Binding-and-Using-Friendly-Enums-in-WPF


0
请看一下这个:

  <Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="AlignmentValues">
      <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="HorizontalAlignment" />
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
  </Window.Resources>

顺便说一句,谷歌是你的好朋友。在这里发帖之前,请先向谷歌提问。

在回答之前,我也做了同样的事情,并为您找到了这个链接。

http://msdn.microsoft.com/en-us/library/bb613576.aspx


1
嗨,在发布答案之前,请始终阅读问题 :) 无论如何,您的解决方案是针对特定的枚举类型而不是所有枚举类型。 - Yaniv
抱歉如果我没有理解问题。我提供给您的解决方案来自于 msdn,我复制粘贴了它。这是标准的做法。我没有编造任何东西。请查看我给您发布的 msdn。 - dev hedgehog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接