注意:代码的格式适合 SO 的设计,不一定是典型的 C# 行(中断)设计,因为我不喜欢水平滚动。
资源文件,Resources.resx:
注意 #1: 您必须将 Access Modifier(上面截图中的右上角)设置为 Public 才能获得访问权限来自其他程序集(在我的情况下是必需的)。
注意 #2: 要利用 Visual Studio 的多语言支持概念,本地化资源文件必须命名为 Resources.xx-XX.resx,例如。 G。 Resources.de-DE.resx。
enum,QuestionType.cs:
namespace Yoda.Data.Interfaces.Enums
{
using System.ComponentModel.DataAnnotations;
using Yoda.Data.Interfaces.Properties;
public enum QuestionType
{
[Display(Name = "Question_Type_Unknown_Entry",
ResourceType = typeof(Resources),
Description = "Question_Type_Unknown_ToolTip")]
Unknown = 0,
[Display(Name = "Question_Type_Question_Entry",
ResourceType = typeof(Resources),
Description = "Question_Type_Question_ToolTip")]
Question = 1,
[Display(Name = "Question_Type_Answer_Entry",
ResourceType = typeof(Resources),
Description = "Question_Type_Answer_ToolTip")]
Answer = 2
}
}
EnumExtensions.cs中的扩展方法:
namespace Yoda.Frontend.Extensions
{
using System;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Resources;
public static class EnumExtensions
{
// This method can be made private if you don't use it elsewhere
public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumValue)
where TAttribute : Attribute
{
var memberInfo = enumValue.GetType().GetMember(enumValue.ToString());
return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false)
.OfType<TAttribute>()
.FirstOrDefault();
}
public static string ToDescription(this Enum enumValue)
{
var displayAttribute = enumValue.GetEnumAttribute<DisplayAttribute>();
return displayAttribute == null
? enumValue.ToString().Replace("_", " ")
: new ResourceManager(displayAttribute.ResourceType)
.GetString(displayAttribute.Description, CultureInfo.CurrentUICulture);
}
public static string ToName(this Enum enumValue)
{
var displayAttribute = enumValue.GetEnumAttribute<DisplayAttribute>();
return displayAttribute == null
? enumValue.ToString().Replace("_", " ")
: new ResourceManager(displayAttribute.ResourceType)
.GetString(displayAttribute.Name, CultureInfo.CurrentUICulture);
}
}
// Your other enum extension methods go here...
}
在 WPF 中需要 2 个转换器(而不是一个带参数的转换器)以符合 SoC 的使用示例如下所示:
Name 属性转换器,QuestionTypeNameConverter.cs:
namespace Yoda.Frontend.Converters
{
using System;
using System.Globalization;
using System.Windows.Data;
using Yoda.Data.Interfaces.Enums;
using Yoda.Frontend.Extensions;
// Second converter would be named QuestionTypeDescriptionConverter
public class QuestionTypeNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
// Second converter would call .ToDescription() instead
return (value as QuestionType? ?? QuestionType.Unknown).ToName();
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
return value;
}
}
}
注意:为了您的阅读乐趣,我将示例限制为仅显示一个转换器类,但我已包含 cmets 来描述第二个转换器所需的更改。
最后是 MainView.xaml 中的用法:
<Window x:Class="Yoda.Frontend.MainView" x:Name="MainWindow">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
// ... more xmlns & other basic stuff
xmlns:c="clr-namespace:CAP.GUI.Converters"
<Window.Resources>
<c:QuestionTypeDescriptionConverter x:Key="QuestionTypeDescription" />
<c:QuestionTypeNameConverter x:Key="QuestionTypeName" />
</Window.Resources>
// Your window layout goes here...
<ComboBox ItemsSource="{Binding QuestionTypes, Mode=OneWay}" Margin="3" Name="QuestionType"
SelectedItem="{Binding SelectedItem.ValidQuestionType,
Converter={StaticResource QuestionTypeName}}"
ToolTip="{Binding SelectedItem.ValidQuestionType,
Converter={StaticResource QuestionTypeDescription}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource QuestionTypeName}}"
ToolTip="{Binding Converter={StaticResource QuestionTypeDescription}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
// Your other window layout goes here...
</Window>