gpt4 book ai didi

c# - 动态绑定(bind)到枚举

转载 作者:太空宇宙 更新时间:2023-11-03 12:50:03 25 4
gpt4 key购买 nike

我想在我的 ViewModel 上有一个枚举,比方说代表一个人的性别。表示 ViewModel 的 View 应该能够提供一种提供该值的方式;无论是一组单选按钮还是组合框(如果有很多)。还有很多示例,您可以在 XAML 中对单选按钮进行硬编码,每个单选按钮说明它代表哪个值。更好的还会使用显示属性的名称来为单选按钮提供文本。

我希望更进一步。我希望它根据 Enum 的值和 DisplayAttribute 的名称和说明等内容动态地生成 RadioButton。理想情况下,如果它超过 6 个项目(可能作为某种控件实现),我希望它选择创建一个 ComboBox(而不是 RadioButtons);但是让我们看看我们是否可以在尝试运行之前走路。 :)

我的谷歌搜索让我非常接近......这是我得到的:

public enum Gender
{
[Display(Name="Gentleman", Description = "Slugs and snails and puppy-dogs' tails")]
Male,

[Display(Name = "Lady", Description = "Sugar and spice and all things nice")]
Female
}

窗口:

<Window x:Class="WpfApplication2.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:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:EnumMultiConverter x:Key="EnumMultiConverter"/>

<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type local:EnumDescriptionProvider}"
x:Key="AdvancedGenderTypeEnum">

<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Gender"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<StackPanel>
<ItemsControl ItemsSource="{Binding Source={StaticResource AdvancedGenderTypeEnum}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="{Binding GroupName}" Content="{Binding Name}" ToolTip="{Binding Description}">
<RadioButton.IsChecked>
<MultiBinding Converter="{StaticResource EnumMultiConverter}" Mode="TwoWay">
<Binding RelativeSource="{RelativeSource AncestorType=ItemsControl}" Path="DataContext.Gender" Mode="TwoWay" />
<Binding Path="Value" Mode="OneWay"/>
</MultiBinding>
</RadioButton.IsChecked>
</RadioButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Window>

枚举描述提供者:

public static class EnumDescriptionProvider
{
public static IList<EnumerationItem> GetValues(Type enumType)
{
string typeName = enumType.Name;
var typeList = new List<EnumerationItem>();

foreach (var value in Enum.GetValues(enumType))
{
FieldInfo fieldInfo = enumType.GetField(value.ToString());
var displayAttribute = (DisplayAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(DisplayAttribute));

if (displayAttribute == null)
{
typeList.Add(new EnumerationItem
{
GroupName = typeName,
Value = value,
Name = value.ToString(),
Description = value.ToString()
});
}
else
{
typeList.Add(new EnumerationItem
{
GroupName = typeName,
Value = value,
Name = displayAttribute.Name,
Description = displayAttribute.Description
});
}
}

return typeList;
}
}

枚举项:

public class EnumerationItem
{
public object GroupName { get; set; }
public object Value { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

还有 MultiConverter(因为 IValueConverter 不能为 ConverterParameter 取一个 Binding):

public class EnumMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0].Equals(values[1]);
}

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

所以我遇到的唯一问题是我无法执行 ConvertBack。但也许有人有一个绝妙的解决方案。正如我所说,理想情况下,我只想要一些可以绑定(bind)到我的 ViewModel 上的枚举的神奇控件,并让它为该枚举的每个值动态创建 RadioButtons。但我会采纳任何我能得到的建议。

最佳答案

我建议您使用自定义行为,这将使您能够将所有 Enum 到 ViewModel 逻辑放入一个可重用的代码段中。这样你就不必纠结于复杂的 ValueConverters

有一篇很棒的文章和 GitHub 示例演示了这个问题的解决方案,请参见下面的链接

WPF – Enum ItemsSource With Custom Behavior - Article

GitHub repository for sample code

希望能给你想要的东西

关于c# - 动态绑定(bind)到枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35890748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com