Joa*_*nge 169 .net c# data-binding wpf xaml
我试图找到一个简单的例子,其中枚举按原样显示.我见过的所有示例都尝试添加漂亮的显示字符串,但我不希望这种复杂性.
基本上我有一个类,它包含我绑定的所有属性,首先将DataContext设置为此类,然后在xaml文件中指定这样的绑定:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Run Code Online (Sandbox Code Playgroud)
但是这并没有在ComboBox
as项中显示枚举值.
Kyr*_*o M 285
您可以通过在Window Loaded
事件处理程序中放置以下代码从代码中执行此操作,例如:
yourComboBox.ItemsSource = Enum.GetValues(typeof(EffectStyle)).Cast<EffectStyle>();
Run Code Online (Sandbox Code Playgroud)
如果需要在XAML中绑定它,则需要使用ObjectDataProvider
创建可用作绑定源的对象:
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:StyleAlias="clr-namespace:Motion.VideoEffects">
<Window.Resources>
<ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="StyleAlias:EffectStyle"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<Grid>
<ComboBox ItemsSource="{Binding Source={StaticResource dataFromEnum}}"
SelectedItem="{Binding Path=CurrentEffectStyle}" />
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
请注意下一个代码:
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:StyleAlias="clr-namespace:Motion.VideoEffects"
Run Code Online (Sandbox Code Playgroud)
指导如何映射您可以在MSDN上阅读的命名空间和程序集.
Nic*_*ick 106
我喜欢我绑定的所有对象都在我的中定义ViewModel
,因此我尽量避免<ObjectDataProvider>
在xaml中使用.
我的解决方案不使用View中定义的数据,也不使用代码隐藏.只有一个DataBinding,一个可重用的ValueConverter,一个获取任何Enum类型描述集合的方法,以及要绑定到ViewModel中的单个属性.
当我想要绑定Enum
到ComboBox
我要显示的文本永远不会匹配的值时Enum
,所以我使用该[Description()]
属性为它提供我实际想要在其中看到的文本ComboBox
.如果我在游戏中有一个字符类枚举,它看起来像这样:
public enum DayOfWeek
{
// add an optional blank value for default/no selection
[Description("")]
NOT_SET = 0,
[Description("Sunday")]
SUNDAY,
[Description("Monday")]
MONDAY,
...
}
Run Code Online (Sandbox Code Playgroud)
首先,我使用几种方法创建了辅助类来处理枚举.一种方法获取特定值的描述,另一种方法获取所有值及其对类型的描述.
public static class EnumHelper
{
public static string Description(this Enum value)
{
var attributes = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
return (attributes.First() as DescriptionAttribute).Description;
// If no description is found, the least we can do is replace underscores with spaces
// You can add your own custom default formatting logic here
TextInfo ti = CultureInfo.CurrentCulture.TextInfo;
return ti.ToTitleCase(ti.ToLower(value.ToString().Replace("_", " ")));
}
public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions(Type t)
{
if (!t.IsEnum)
throw new ArgumentException($"{nameof(t)} must be an enum type");
return Enum.GetValues(t).Cast<Enum>().Select((e) => new ValueDescription() { Value = e, Description = e.Description() }).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们创建一个ValueConverter
.继承MarkupExtension
使得在XAML中使用更容易,因此我们不必将其声明为资源.
[ValueConversion(typeof(Enum), typeof(IEnumerable<ValueDescription>))]
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return EnumHelper.GetAllValuesAndDescriptions(value.GetType());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
我ViewModel
只需要一个属性,我View
可以绑定到组合框SelectedValue
和ItemsSource
组合框:
private DayOfWeek dayOfWeek;
public DayOfWeek SelectedDay
{
get { return dayOfWeek; }
set
{
if (dayOfWeek != value)
{
dayOfWeek = value;
OnPropertyChanged(nameof(SelectedDay));
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后绑定ComboBox
视图(使用ValueConverter
的ItemsSource
绑定)...
<ComboBox ItemsSource="{Binding Path=SelectedDay, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=SelectedDay}" />
Run Code Online (Sandbox Code Playgroud)
要实现此解决方案,您只需复制我的EnumHelper
类和EnumToCollectionConverter
类.他们将与任何枚举一起使用.此外,我没有在这里包含它,但是这个ValueDescription
类只是一个带有2个公共对象属性的简单类,一个叫做Value
,一个叫做Description
.您可以自己创建,也可以更改代码以使用Tuple<object, object>
或KeyValuePair<object, object>
tom*_*ska 46
我使用了另一种使用MarkupExtension的解决方案.
我做了一个提供项目来源的课程:
public class EnumToItemsSource : MarkupExtension
{
private readonly Type _type;
public EnumToItemsSource(Type type)
{
_type = type;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Enum.GetValues(_type)
.Cast<object>()
.Select(e => new { Value = (int)e, DisplayName = e.ToString() });
}
}
Run Code Online (Sandbox Code Playgroud)这几乎都是......现在在XAML中使用它:
<ComboBox DisplayMemberPath="DisplayName"
ItemsSource="{persons:EnumToItemsSource {x:Type enums:States}}"
SelectedValue="{Binding Path=WhereEverYouWant}"
SelectedValuePath="Value" />
Run Code Online (Sandbox Code Playgroud)将"枚举:状态"更改为您的枚举
dru*_*uss 22
使用ObjectDataProvider:
<ObjectDataProvider x:Key="enumValues"
MethodName="GetValues" ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:ExampleEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
Run Code Online (Sandbox Code Playgroud)
然后绑定到静态资源:
ItemsSource="{Binding Source={StaticResource enumValues}}"
Run Code Online (Sandbox Code Playgroud)
小智 14
它工作起来非常好而且简单。
xaml
<ComboBox ItemsSource="{Binding MyEnumArray}">
Run Code Online (Sandbox Code Playgroud)
。CS
public Array MyEnumArray
{
get { return Enum.GetValues(typeof(MyEnum)); }
}
Run Code Online (Sandbox Code Playgroud)
小智 9
尼克的回答确实帮助了我,但我意识到它可以稍微调整一下,以避免额外的类,ValueDescription.我记得框架中已经存在KeyValuePair类,因此可以使用它.
代码只是略有变化:
public static IEnumerable<KeyValuePair<string, string>> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable
{
if (!typeof(TEnum).IsEnum)
{
throw new ArgumentException("TEnum must be an Enumeration type");
}
return from e in Enum.GetValues(typeof(TEnum)).Cast<Enum>()
select new KeyValuePair<string, string>(e.ToString(), e.Description());
}
public IEnumerable<KeyValuePair<string, string>> PlayerClassList
{
get
{
return EnumHelper.GetAllValuesAndDescriptions<PlayerClass>();
}
}
Run Code Online (Sandbox Code Playgroud)
最后是XAML:
<ComboBox ItemSource="{Binding Path=PlayerClassList}"
DisplayMemberPath="Value"
SelectedValuePath="Key"
SelectedValue="{Binding Path=SelectedClass}" />
Run Code Online (Sandbox Code Playgroud)
我希望这对其他人有帮助.
您需要在枚举中创建一个值数组,可以通过调用System.Enum.GetValues()创建它,并将其传递给Type
您想要项目的枚举.
如果为ItemsSource
属性指定了此属性,则应使用所有枚举值填充它.你可能要绑定SelectedItem
到EffectStyle
(假设它是相同的枚举的属性,包含当前值).
这个问题有很多很好的答案,我谦虚地提交我的答案。我发现我的更简单、更优雅。它只需要一个值转换器。
给定一个枚举...
public enum ImageFormat
{
[Description("Windows Bitmap")]
BMP,
[Description("Graphics Interchange Format")]
GIF,
[Description("Joint Photographic Experts Group Format")]
JPG,
[Description("Portable Network Graphics Format")]
PNG,
[Description("Tagged Image Format")]
TIFF,
[Description("Windows Media Photo Format")]
WDP
}
Run Code Online (Sandbox Code Playgroud)
和一个值转换器...
public class ImageFormatValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is ImageFormat format)
{
return GetString(format);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string s)
{
return Enum.Parse(typeof(ImageFormat), s.Substring(0, s.IndexOf(':')));
}
return null;
}
public string[] Strings => GetStrings();
public static string GetString(ImageFormat format)
{
return format.ToString() + ": " + GetDescription(format);
}
public static string GetDescription(ImageFormat format)
{
return format.GetType().GetMember(format.ToString())[0].GetCustomAttribute<DescriptionAttribute>().Description;
}
public static string[] GetStrings()
{
List<string> list = new List<string>();
foreach (ImageFormat format in Enum.GetValues(typeof(ImageFormat)))
{
list.Add(GetString(format));
}
return list.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
资源...
<local:ImageFormatValueConverter x:Key="ImageFormatValueConverter"/>
Run Code Online (Sandbox Code Playgroud)
XAML 声明...
<ComboBox Grid.Row="9" ItemsSource="{Binding Source={StaticResource ImageFormatValueConverter}, Path=Strings}"
SelectedItem="{Binding Format, Converter={StaticResource ImageFormatValueConverter}}"/>
Run Code Online (Sandbox Code Playgroud)
查看型号...
private ImageFormat _imageFormat = ImageFormat.JPG;
public ImageFormat Format
{
get => _imageFormat;
set
{
if (_imageFormat != value)
{
_imageFormat = value;
OnPropertyChanged();
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果组合框...