枚举类型的组合框转换器

4

我有一个枚举类型,其值为HomeRun、StolenBase、FirstBase等。

我想在组合框中显示这些值,并在大写字母之前插入空格,以便显示为“Home Run”、“Stolen Base”等。

我已经有了能够执行格式化的代码,并将该代码添加到IValueConverter实现的“Convert”方法中。

我的问题是,在XAML中我需要在哪里使用这个转换器,才能使下拉列表和显示的值都具有这种格式?我是否还需要实现ConvertBack?

我很清楚如何设置枚举类型的“描述”,并使用流行的EnumToDescriptionConverter,但我宁愿避免使用它。

5个回答

7

我不确定是否有更好的方法,但是您可以使用ItemTemplate实现您想要的功能。

<ComboBox.ItemTemplate>
    <DataTemplate>
        <ContentPresenter
            Content="{Binding Converter={StaticResource baseballEnumConverter}}"/>
     </DataTemplate>
</ComboBox.ItemTemplate>

这将在您的ComboBox中显示转换后的值。
ComboBox的SelectedValue仍然是枚举值。您不需要实现ConvertBack。

谢谢。这对于下拉菜单确实有效,但显示的值仍然是枚举值。这是因为我绑定了SelectedValue吗? - user981225
我不确定。当我绑定SelectedValue时,ViewModel被设置为枚举值(这是正确的行为),而显示的组合框值是格式化后的值。你能发布你的Combobox xaml和你的ViewModel绑定吗? - wdavo

2

[更新] 我回答的关键点是枚举值被完全转换了。我认为这种方法比每个枚举值都转换要容易。[/更新]

我需要在xaml中使用这个转换器吗,这样不仅下拉列表,显示的值也会有这种格式吗?

在ComboBox的Binding ItemsSource处ItemsSource="{Binding Source={x:Null}, Converter={StaticResource converter}}"),请检查以下代码。

我需要实现ConvertBack吗?

不需要,因为在运行时您无法修改枚举,即使可以,您也无法在VIEW中更改ComboBox的ItemsSource,这意味着Binding Mode是OneWay。

XAML

<Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MyEnumConverter x:Key="converter"/>
    </Window.Resources>
    <StackPanel>
        <ComboBox ItemsSource="{Binding Source={x:Null}, Converter={StaticResource converter}, Mode=OneWay}"></ComboBox>
    </StackPanel>
</Window>

代码

public enum MyEnum
{
    HomeRun, StolenBase, FirstBase
}

[ValueConversion(typeof(object), typeof(List<string>))]
public class MyEnumConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var names = Enum.GetNames(typeof (MyEnum)).ToArray();
        //Add some code to support the thing you want to do(add blank in front of Capital...)
        return names;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

如果没有实现ConvertBack,那么选定的值将如何转换回枚举类型? - Kirk Broadhurst
我认为枚举的整个值都可以进行转换。有没有任何原因需要将每个枚举值进行转换? - Jin-Wook Chung
是的,枚举需要进行转换,当您调用 GetNames 并在字符串前添加空白时,您正在进行转换。ComboBox 只知道关于一个 List<string>,所以需要将其映射回枚举值。 - Kirk Broadhurst
为什么将代码中的字符串值转换为枚举值放在ConvertBack方法中?此外,您能够访问ConvertBack方法吗?(我不想让您感到不愉快。我认为这种讨论对我们有好处。如果我犯了错误或有误解,请告诉我。) - Jin-Wook Chung
好的讨论 :) ComboBox 只知道 List<string> - 但我们想要将 SelectedItem 绑定到 ViewModel 中的一个枚举。那么我们如何将 SelectedItem(一个 string)转换为枚举?我发现我的解决方案行不通,但我认为我们需要在 某个地方 进行 string->enum 转换... - Kirk Broadhurst
是的,我认为可以在ViewModel的属性设置器中编写代码,绑定ComboBox的SelectedItem,但我们不知道提问者确切想要做什么。让我们把这个问题留给他自己去解决。 - Jin-Wook Chung

1

如果您希望将ComboBox的选定值“转换回”枚举,则需要实现ConvertBack

个人建议采用您提到的描述属性模式,因为

  1. 显而易见的问题已经被问过了,而且
  2. 您不仅限于在大写字母处插入空格-您可以使用任何描述。

但是假设您想采用此模式,只需正确编写转换器即可。我建议像这样:

// Convert method
var formattedNames = new List<string>();
foreach (var value in Enum.GetValues(typeof(Things)))
{
    // Format is a method to convert the enum value to the display string
    var formattedName = Format(value);
    formattedNames.Add(formattedName);
}
// return a list of strings that you can bind to
return formattedNames;

// ConvertBack method
// Unformat is a method to revert the display string back to the enum value
var value = Unformat(formattedValue);
return Enum.Parse(typeof(Things), value);

你也可以创建一个简单的类来保存显示值和枚举值,然后适当地设置组合框的DisplayPath属性。

class DisplayEnum
{
    public string DisplayValue { get;set; }
    public MyEnum ActualValue { get;set; }
}

<ComboBox DisplayMemberPath=DisplayValue ...

编辑

我意识到这不起作用,因为ConvertBack试图将字符串转换为枚举,但实际绑定集是List<string>。我会把它留在这里,因为它是朝着正确方向的一步。

我相信你需要两个转换器:

  1. 将枚举类型转换为一组枚举值,以及
  2. 将枚举值转换为字符串。这第二个转换器应该实现ConvertBack方法。

正如我指出的,如果您不实现ConvertBack那么您将无法将SelectedValue绑定回ViewModel上的枚举属性。


你在convert方法中返回了List<string>类型,因此在convertback方法中你将会收到List<string>类型的参数。你如何声明convertback中的formatedValue - Jin-Wook Chung
@jwJung 你说得对 - 或许需要两个转换器;一个将枚举类型转换为集合(用于项绑定),另一个则将项格式化/反格式化为漂亮的字符串值。 - Kirk Broadhurst
我认为是这样的。我和你进行了很好的讨论,认为你的答案和我的答案并没有太大的不同。 - Jin-Wook Chung

0
你需要创建一个字典或其他查找结构,将枚举值映射到字符串表示形式。

-1

2
你的博客比jwJung和我的回答都要短得多;发布一些简单的博客链接是不够的。此外,你的回答是一个代码后台解决方案,而不是XAML解决方案。 - Kirk Broadhurst
虽然从理论上讲这可能回答了问题,但最好在此处包括答案的实质部分,并提供参考链接。参考链接 - Bill the Lizard
我曾天真地认为这会有所帮助。不再这样做了。 - Mike Verrier

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