using System.ComponentModel; using System.Reflection; using System.Windows.Controls.Primitives; using System.Windows.Markup; namespace VariaStudio.Markup { /// /// 用于在XAML中提供枚举类型的值源扩展。此扩展允许开发者直接将枚举类型作为数据源,适用于如ComboBox等控件的ItemsSource绑定。 /// public class EnumSourceExtension : MarkupExtension { private Type? enumType; /// /// 获取或设置一个值,指示是否将枚举项绑定到其 DescriptionAttribute 的描述。如果设置为 true,则返回的枚举项将包含描述信息,并且只能通过 SelectedValue 来绑定源属性。 /// /// 当此属性设置为 true 时,提供给 UI 的数据源将会是带有 Value 和 Description 属性的对象列表。其中 Value 对应于枚举值,而 Description 则是从枚举成员上的 DescriptionAttribute 中获取的描述文本。 public bool BindToDescription { get; set; } = false; /// /// 获取或设置用作数据源的枚举类型。此属性允许开发者指定一个枚举类型,该类型将作为控件(如ComboBox)的数据源。 /// /// 当设置了此属性后,对应的控件会使用指定的枚举类型的所有成员作为其数据项。如果需要展示枚举成员上的描述信息,请同时设置 BindToDescription 属性为 true,并通过 SelectedValue 绑定源属性。 public Type? EnumType { get => enumType; set { if (value == enumType) return; if (null != value) { var type = Nullable.GetUnderlyingType(value) ?? value; if (!type.IsEnum) { throw new ArgumentException("类型必须是枚举类型"); } } enumType = value; } } /// /// 用Markup语法,绑定枚举类型 /// /// ItemsSource="{controls:EnumSource EnumType=controls:Sex}" public EnumSourceExtension() { } /// /// 用Markup语法,绑定枚举类型 /// /// /// 若需要绑定Description,则需设置BindToDescription为True,同时只能用SelectedValue来绑定源属性 /// ItemsSource="{controls:EnumSource controls:ExampleEnum}" public EnumSourceExtension(Type enumType) { EnumType = enumType; } /// public override object? ProvideValue(IServiceProvider serviceProvider) { if (serviceProvider.GetService(typeof(IProvideValueTarget)) is not IProvideValueTarget pvt) { return null; } //如果为空,则返回运行时绑定的类。 if (pvt.TargetObject is not FrameworkElement) { return this; } if (enumType == null) return null; var enumValues = Enum.GetValues(enumType); if (!BindToDescription) return enumValues; var items = new List(); foreach (var enumValue in enumValues) { var item = new { Value = enumValue, Description = GetDescription(enumValue) }; items.Add(item); } if (pvt.TargetObject is Selector selector) { selector.DisplayMemberPath = "Description"; selector.SelectedValuePath = "Value"; } return items; } private static string? GetDescription(object? enumValue) { if (enumValue == null) return string.Empty; var fieldInfo = enumValue.GetType().GetField(enumValue.ToString() ?? string.Empty); var descriptionAttribute = fieldInfo?.GetCustomAttribute(); return descriptionAttribute?.Description ?? enumValue.ToString(); } } }