WPF 的 ComboBox 控件等绑定 enum 值很繁琐,很让人头疼,网上也有提供了一些方法,基本是使用 ObjectDataProvider 方式和 MarkupExtension 方式,
有没有办法绑定值为 enum 类型就自动加载所有枚举值选项,下面记录一种方法;
主要通过附加属性,根据绑定的 Selecter.SelectedItem 属性,获取属性类型,再获取枚举值的集合了,下面是实现代码:
public class ItemsControlHelper
{
/// <summary>
/// 绑定 enum 类型所有值给 ItemsSource 赋值
/// 必须绑定 SelectedItem
/// </summary>
public static readonly DependencyProperty EnumValuesToItemsSourceProperty = DependencyProperty.RegisterAttached(
"EnumValuesToItemsSource", typeof(bool), typeof(ItemsControlHelper), new PropertyMetadata(default(bool), OnEnumValuesToItemsSourceChanged));
public static void SetEnumValuesToItemsSource(DependencyObject element, bool value)
{
element.SetValue(EnumValuesToItemsSourceProperty, value);
}
public static bool GetEnumValuesToItemsSource(DependencyObject element)
{
return (bool)element.GetValue(EnumValuesToItemsSourceProperty);
}
private static void OnEnumValuesToItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ItemsControl itemsControl && GetEnumValuesToItemsSource(itemsControl))
{
if (itemsControl.IsLoaded)
{
SetItemsSource(itemsControl);
}
else
{
itemsControl.Loaded += ItemsControl_Loaded;
}
}
}
private static void SetItemsSource(ItemsControl itemsControl)
{
var itemsBindingExpression = BindingOperations.GetBinding(itemsControl, ItemsControl.ItemsSourceProperty);
if (itemsBindingExpression != null)
{
throw new InvalidOperationException("When using ItemsControlHelper.EnumValuesToItemsSource, cannot be used ItemsSource at the same time.");
}
if (itemsControl.Items.Count > 0)
{
throw new InvalidOperationException("When using ItemsControlHelper.EnumValuesToItemsSource, Items Collection must be null");
}
var bindingExpression = BindingOperations.GetBindingExpression(itemsControl, Selector.SelectedItemProperty);
if (bindingExpression == null)
{
throw new InvalidOperationException("ItemsControl must be binding SelectedItem property");
}
var binding = bindingExpression.ParentBinding;
var dataType = bindingExpression.DataItem?.GetType();
var paths = binding.Path.Path.Split('.');
foreach (var path in paths)
{
var propertyInfo = dataType?.GetProperty(path);
if (propertyInfo == null)
{
return;
}
dataType = propertyInfo.PropertyType;
}
if (!dataType!.IsEnum)
{
var underlyingType = Nullable.GetUnderlyingType(dataType);
if (underlyingType == null)
{
return;
}
dataType = underlyingType;
}
var itemsSourceBinding = new Binding();
itemsSourceBinding.Source = Enum.GetValues(dataType);
itemsSourceBinding.Mode = BindingMode.OneWay;
itemsControl.SetBinding(ItemsControl.ItemsSourceProperty, itemsSourceBinding);
}
private static void ItemsControl_Loaded(object sender, RoutedEventArgs e)
{
var itemsControl = (ItemsControl)sender;
itemsControl.Loaded -= ItemsControl_Loaded;
SetItemsSource(itemsControl);
}
}
public class MainViewModel : ObservableObject
{
private Animal animal;
public Animal Animal
{
get { return animal; }
set { SetProperty(ref animal, value); }
}
}
public enum Animal
{
Dog = 0,
Cat,
Elephant,
Bird,
Lion,
Tiger
}
<Grid>
<ComboBox Width="120"
HorizontalAlignment="Center"
VerticalAlignment="Center"
local:ItemsControlHelper.EnumValuesToItemsSource="True"
SelectedItem="{Binding Animal}" />
</Grid>

public class EnumDescriptionConverter : EnumConverter
{
public EnumDescriptionConverter(Type type)
: base(type)
{
}
/// <inheritdoc/>
public override object ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type? destinationType)
{
if (destinationType == typeof(string))
{
if (value != null)
{
FieldInfo? fieldInfo = value.GetType()!.GetField(value.ToString()!);
if (fieldInfo != null)
{
var attribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>(inherit: false);
if (attribute != null)
{
return !string.IsNullOrEmpty(attribute.Description) ? attribute.Description : value.ToString()!;
}
}
return value.ToString()!;
}
}
return string.Empty;
}
}
枚举添加 Attribute 注释内容
[TypeConverter(typeof(EnumDescriptionConverter))]
public enum Animal
{
[Description("小狗")]
Dog = 0,
[Description("小猫")]
Cat,
[Description("大象")]
Elephant,
[Description("小鸟")]
Bird,
[Description("狮子")]
Lion,
[Description("小脑斧")]
Tiger
}
再次运行代码结果

同理继承 Selector 的控件也可以使用,例如 ListBox :

最后只需要添加一行代码 local:ItemsControlHelper.EnumValuesToItemsSource="True",就可以自动绑定 ItemsSource,xaml 代码不需要再去关注 enum 的类型。
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功
在Ruby中,我试图理解to_enum和enum_for方法。在我提出问题之前,我提供了一些示例代码和两个示例来帮助理解上下文。示例代码:#replicatesgroup_bymethodonArrayclassclassArraydefgroup_by2(&input_block)returnself.enum_for(:group_by2)unlessblock_given?hash=Hash.new{|h,k|h[k]=[]}self.each{|e|hash[input_block.call(e)]示例#1:irb(main)>puts[1,2,3].group_by2.ins
我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排
我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?
昨晚,我在思考我认为是高级ruby语言的功能,即Continuations(callcc)和Bindingobjects。我的意思是高级,因为我有静态类型的oo语言背景(C#、Java、C++),我最近才发现ruby,所以这些语言特性对我来说不是很熟悉。我想知道这些语言功能在现实世界中的用途是什么。根据我的经验,一切都可以用静态类型的oo语言来完成,但有时我不太同意。我想我在阅读SamRuby的那篇好文章时发现了Continuation的美妙之处/兴趣:http://www.intertwingly.net/blog/2005/04/13/Continuations-for-C