using System.ComponentModel;
using System.Reflection;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
namespace NeumUI.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;
}
}
///
/// 在ResourceDictionary中声明
///
/// local:EnumSourceExtension x:Key="EnumBindingSource" EnumType="{x:AppearanceType local:Sex}"
/// ItemsSource="{local:EnumSource EnumType=local:ExampleEnum}" SelectedItem="{Binding ExampleEnum}"
public EnumSourceExtension()
{
}
///
/// 用Markup语法
///
///
/// 若需要绑定Description,则需设置BindToDescription为True,同时只能用SelectedValue来绑定源属性
/// ItemsSource="{Binding Source={local:EnumTypeBindingSource {x:AppearanceType local:ExampleEnum}}}"
public EnumSourceExtension(Type enumType) { EnumType = enumType; }
///
public override object? ProvideValue(IServiceProvider serviceProvider)
{
var pvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
if (pvt == null) { return null; }
//如果为空,则返回运行时绑定的类。
if (pvt.TargetObject is not FrameworkElement) { return this; }
if (enumType != null)
{
var enumValues = Enum.GetValues(enumType);
if (!BindToDescription) return enumValues;
var items = new List