gpt4 book ai didi

c# - WPF 工具包 : CheckComboBox and [Flags] enum

转载 作者:行者123 更新时间:2023-12-04 01:57:12 24 4
gpt4 key购买 nike

我正在使用 Xceed Extended WPF Toolkit 在 PropertyGrid 中显示带有 [Flags] 属性的枚举。

[Flags]             
public enum TestEnum
{
Test1 = 1,
Test2 = 2,
Test3 = 4,
Test4 = 8,
Test5 = 16,
Test6 = 32,
Test7 = 64,
}

因为我无法在编译时知道枚举定义,所以我会使用 EnumBuilder 动态创建一个枚举.

我创建了一个编辑器来将枚举显示为 CheckComboBox:

public class CheckComboBoxEditor : TypeEditor<CheckComboBox>, ITypeEditor
{
protected override void SetValueDependencyProperty()
{
ValueProperty = CheckComboBox.SelectedValueProperty;
}

protected override CheckComboBox CreateEditor()
{
return new CheckComboBox();
}

protected override void ResolveValueBinding(PropertyItem propertyItem)
{
var _binding = new Binding("Value");
_binding.Source = propertyItem;
_binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
_binding.Mode = BindingMode.TwoWay;
_binding.Converter = CreateValueConverter();
BindingOperations.SetBinding(Editor, CheckComboBox.SelectedValueProperty, _binding);

var _binding2 = new Binding("Value");
_binding2.Source = propertyItem;
_binding2.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
_binding2.Mode = BindingMode.TwoWay;
_binding2.Converter = CreateValueConverter();
BindingOperations.SetBinding(Editor, CheckComboBox.SelectedItemProperty, _binding2);

Editor.ItemsSource = Enum.GetValues(propertyItem.Value.GetType());
}
}

如您所见,到目前为止,我已尝试分别绑定(bind) SelectedValueSelectedItem 属性。 CreateValueConverter() 在基类中定义并返回 null

如果我在框中选择一些值并点击我的保存按钮,它会很好地工作 - 在我的模型中,我收到正确的枚举值。但它在另一个方向上不起作用 - 如果我为我的属性设置任何枚举值(有或没有标志),所有值都未选中并且内容区域是

你有解决这个问题的想法吗?

最佳答案

在这种情况下,对于带有 FlagsAttribute 的枚举,最通用的解决方案是为枚举的所有项目和选定项目使用 VM 中的特定字段。类似的东西:

XAML

<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>

<xctkpg:PropertyGrid Grid.Row="1" SelectedObject="{Binding CurrentObject}" AutoGenerateProperties="False">
<xctkpg:PropertyGrid.EditorDefinitions>
<xctkpg:EditorTemplateDefinition TargetProperties="{x:Type local:TestEnum}">

<xctkpg:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<xctk:CheckComboBox ItemsSource="{Binding Instance.Items}" SelectedValue="{Binding Instance.SelValue}" />
</DataTemplate>
</xctkpg:EditorTemplateDefinition.EditingTemplate>

</xctkpg:EditorTemplateDefinition>
</xctkpg:PropertyGrid.EditorDefinitions>
<xctkpg:PropertyGrid.PropertyDefinitions>
<xctkpg:PropertyDefinition TargetProperties="Value" />
</xctkpg:PropertyGrid.PropertyDefinitions>
</xctkpg:PropertyGrid>

</Grid>

C#

class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private ItemViewModel _currentObject = new ItemViewModel() { Value = TestEnum.Test3 | TestEnum.Test7 };
public ItemViewModel CurrentObject
{
get { return _currentObject; }
set
{
_currentObject = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentObject)));
}
}
}


public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private TestEnum _value;
public TestEnum Value
{
get { return _value; }
set
{
_value = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelValue)));
}
}

public string SelValue
{
get
{
return String.Join(",", Enum.GetValues(typeof(TestEnum)).OfType<TestEnum>().Where(v => (_value & v) != 0).Select(v => v.ToString()));
}
set
{
_value = value.Split(new[] { ','}, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).
Aggregate((TestEnum)0, (acc, val) => acc | (TestEnum)Enum.Parse(typeof(TestEnum), val));

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelValue)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
}
}

public ObservableCollection<string> Items
{
get
{
return new ObservableCollection<string>(Enum.GetNames(typeof(TestEnum)));
}
}
}

2016 年 1 月 31 日更新为了使代码适用于动态生成的枚举,我进行了以下更改:

XAML

 <xctkpg:EditorTemplateDefinition TargetProperties="Value">

C#

public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

public static readonly Type EnumType = GenerateEnumType();

private object _value;
public object Value
{
get { return _value; }
set
{
_value = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelValue)));
}
}

public string SelValue
{
get
{
return String.Join(",",
Enum.GetValues(EnumType).OfType<object>().Where(v => ((int)_value & (int)v) != 0).Select(v => v.ToString()));
}
set
{
var strings = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim());
_value = Enum.ToObject(EnumType, strings.Aggregate(0, (acc, val) => acc | (int)Enum.Parse(EnumType, val)));


PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelValue)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
}
}

public ObservableCollection<string> Items
{
get
{
return new ObservableCollection<string>(Enum.GetNames(EnumType));
}
}

public static Type GenerateEnumType()
{
string asmNameString = "flags_enum";

// Create Base Assembly Objects
AppDomain appDomain = AppDomain.CurrentDomain;
AssemblyName asmName = new AssemblyName(asmNameString);
AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);

// Create Module and Enumeration Builder Objects
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(asmNameString + "_module");
EnumBuilder enumBuilder = modBuilder.DefineEnum(asmNameString, TypeAttributes.Public, typeof(int));

Type fa = typeof(FlagsAttribute);


CustomAttributeBuilder attributeBuilder =
new CustomAttributeBuilder(fa.GetConstructor(new Type[0]), new object[0]);

enumBuilder.SetCustomAttribute(attributeBuilder);

for (int i = 0; i < 7; i++)
{
enumBuilder.DefineLiteral($"Test{i + 1}", 1 << i);
}

return enumBuilder.CreateType();
}
}

现在 ItemViewModel 的值可以这样设置:

ItemViewModel vm = new ItemViewModel();
vm.Value = Enum.ToObject(ItemViewModel.EnumType, 33);

关于c# - WPF 工具包 : CheckComboBox and [Flags] enum,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34941352/

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