wpf 何时使用C#中的枚举

nsc4cvqm  于 2022-12-24  发布在  C#
关注(0)|答案(4)|浏览(198)

我正在创建一个WPF应用程序,并尝试为同一类的不同对象分配优先级。为此,我使用了以下枚举类型:

public enum PriorityLevel 
{
    LEVEL1 = 1,
    LEVEL2 = 2,
    LEVEL3 = 3
}

基本上,根据我使用的条件,对象的PLevel属性(类型为PriorityLevel)被设置为枚举中定义的某个LEVEL。
我的问题是,当我在接口中显示该属性时(在XAML中有一个绑定),它(显然)显示为“LEVEL1”或“LEVEL2”或“LEVEL3”。
我很想知道如何显示“LEVEL1”(带空格)而不是显示“LEVEL1”,问题是我不能在枚举中定义带空格或数字的标识符。
有没有可能枚举不是实现我想要的东西的最佳方式?
在我看来,这似乎是一个适当和有秩序的做法,但也许这不是正确的做法。
我也考虑过为优先级创建一个类,但我希望用一种更简单的方式来解决它。

iq3niunx

iq3niunx1#

您的问题是**何时在C#**中使用枚举,查看此问题的一种方法是询问为值分配人类可读的别名是否提供了某种好处(或没有)。
我看到您有自己的answered问题,在“将对象的Priority属性更改为int类型”(这很有意义)之后,您可以使用一种简单而优雅的方式来格式化基于PLevel的字符串,从而解决了您针对 binding 提出的问题:
我的问题是,当我在接口中显示该属性时(在XAML中有一个绑定),它(显然)显示为“LEVEL1”或“LEVEL2”或“LEVEL3”。我想知道如何显示“LEVEL1”(带空格),而不是显示“LEVEL1”。
或者,一种xaml友好的方法 * 也 * 解决了这个问题,可以与intenum一起工作,并提供了更大的灵活性,这种方法是实现IValueConverter类,并在xaml中将其作为Text="{Binding Path=PriorityLevel, Converter={StaticResource PriorityLevelConverter}}"调用。

// Returns a formatted version of PriorityLevel.
// Works for EITHER int or enum
public class PriorityLevelToFormatted : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
        => $"Level {(int)value}";
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        throw new NotImplementedException("Unused");
}

这样做的一个好处是,您可以使用 * 不同 * 的标准将PLevel转换为 * 其他 * 类型。那么,如果您制作一个转换器,为高于1的电平启用“Hyper”会怎样呢?

public class PriorityLevelToVisibility : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => (int)value == 1 ? Visibility.Hidden : Visibility.Visible;
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        throw new NotImplementedException("Unused");
}

对于testing,我使用了这个最小的WPF形式:

<iv:Window x:Class="wpf_window_ex.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpf_window_ex"
        xmlns:iv="clr-namespace:IVSoftware"
        mc:Ignorable="d"
        Title="Main Window" Height="200" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <local:PriorityLevelToFormatted x:Key="PriorityLevelConverter"/>
        <local:PriorityLevelToVisibility x:Key="PriorityLevelToHyper"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="60"/>
            <RowDefinition Height="40"/>
            <RowDefinition Height="40"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock 
            Visibility="{Binding Path=PLevel, Converter={StaticResource PriorityLevelToHyper}}"
            Text="Hyper Enabled"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Background="LightGreen"
            Grid.Row="1"/>
        <TextBlock 
            Name ="textLevel"
            Text="{Binding Path=PLevel, Converter={StaticResource PriorityLevelConverter}}"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Grid.Row="2"/>
        <Button
            Command="{Binding AdvancePriorityCommand}"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Width="150"
            Grid.Row="3">
            <TextBlock>Advance Level</TextBlock>
        </Button>
    </Grid>
</iv:Window>
bsxbgnwa

bsxbgnwa2#

最好的方法是使用Description属性和扩展方法。
枚举将是:

public enum PriorityLevel 
{
    [Description("LEVEL 1")]
    LEVEL1 = 1,
    [Description("LEVEL 2")]
    LEVEL2 = 2,
    [Description("LEVEL 3")]
    LEVEL3 = 3
}

我经常使用的扩展方法是

public static string GetDescription<T>(this T enumerationValue)
        where T : struct
    {
        var type = enumerationValue.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException($"{nameof(enumerationValue)} must be of Enum type", nameof(enumerationValue));
        }
        var memberInfo = type.GetMember(enumerationValue.ToString());
        if (memberInfo.Length > 0)
        {
            var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attrs.Length > 0)
            {
                return ((DescriptionAttribute)attrs[0]).Description;
            }
        }
        return enumerationValue.ToString();
    }

extension方法检查struct是否为enum,然后使用反射查找DescriptionAttribute(当在类、属性、枚举值等上使用属性时,C#知道Attribute是不必要的),然后返回文本。如果枚举没有DescriptionAttribute,则返回ToString()

nbnkbykc

nbnkbykc3#

枚举绝对是记录这些数据的正确类型--可能值的数量有限,并且它们之间有一个定义好的顺序。
对于显示问题,可以向每个枚举值添加说明。

public enum PriorityLevel 
{
    [Description("LEVEL 1")]
    LEVEL1 = 1,
    [Description("LEVEL 2")]
    LEVEL2 = 2,
    [Description("LEVEL 3")]
    LEVEL3 = 3
}

帮助器方法可以获取枚举值的说明

public static class perEnumHelper
{
    public static string Description(this Enum value)
    {
        var fieldInfo = value.GetType().GetField(value.ToString());
        var attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)
            .Cast<DescriptionAttribute>()
            .ToList();
        return attributes.Any() 
            ? attributes.First().Description 
            : value.ToString();
    }
}
i86rm4rw

i86rm4rw4#

我通过获取枚举项的值并将对象的Priority属性更改为int类型来解决这个问题。
在代码隐藏中:

PLevel = (int)Enum.Parse(typeof(PriorityLevel), PriorityLevel.LEVEL1.ToString());

在XAML中:

Binding="{Binding PLevel, StringFormat={}LEVEL {0}}"

相关问题