WPF ComboBox/ListBox与MultiSelect基于带标志的枚举

soh*_*hum 5 c# enums flags datagrid wpftoolkit

所以我可能只是稍微推动了界限......

基本上我有以下枚举,用C#代码声明:

[Flags]
public enum FlaggedEnum : int
{
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    Option4 = 8,
    ...
    Option16 = 32768,
    None = 0
}
Run Code Online (Sandbox Code Playgroud)

此枚举是我已成功绑定到DataGrid对象的对象的成员.成功意味着我已成功绑定所有其他字段.:)

我想在这里实现的是一个控件,其中检查上面所有适当的选项,其行为和行为类似于ComboBox/ListBox.因此,您单击该字段并弹出一个下拉菜单,可以"检查"所需的任何选项.

控件还必须能够从枚举中读取并写入枚举.

我是WPF新手所以我不知道在哪里可以创建一个ComboBox并绑定到列...任何帮助将不胜感激!

Ego*_*gor 6

我有一个方法可能有效。我对此没有任何功劳 - 我在网上找到了这个方法,但忘记保存地址。

在我的项目中,我需要将一些复选框绑定到标志枚举。为了提供帮助,我找到了一个简单的值转换器的实现来促进双向绑定。它不是通用的,并且转换器的单个实例一次只能与一个目标(意味着一个值的一个实例及其一组复选框)一起工作。转换器使用存储的值引用作为转换回来的方式,因此如果您尝试在单独的对象实例之间重用它,它将无法工作。也就是说,这是我对此类东西的唯一用途,而且它的作用就像一个魅力。

转换器:

/// <summary>
/// Provides for two way binding between a TestErrors Flag Enum property and a boolean value.
/// TODO: make this more generic and add it to the converter dictionary if possible
/// </summary>
public class TestActionFlagValueConverter : IValueConverter {
    private TestErrors target;

    public TestActionFlagValueConverter() {

    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        TestErrors mask = (TestErrors)parameter;
        this.target = (TestErrors)value;
        return ((mask & this.target) != 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        this.target ^= (TestErrors)parameter;
        return this.target;
    }
}
Run Code Online (Sandbox Code Playgroud)

在 xaml 中,它的使用方式如下:

<StackPanel.Resources>
    <local:TestActionFlagValueConverter x:Key="TestActionFlagValueConverter"/>
</StackPanel.Resources>

<CheckBox IsChecked="{Binding Errors, Converter={StaticResource TestActionFlagValueConverter}, ConverterParameter={x:Static local:TestErrors.PowerFailure}...
<CheckBox IsChecked="{Binding Errors, Converter={StaticResource TestActionFlagValueConverter}, ConverterParameter={x:Static local:TestErrors.OpenCondition}...
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可以将其放入数据单元模板中(尽管显然您可能更喜欢使用组合框而不是简单的堆栈面板)。请确保实例化靠近复选框组容器的转换器,以确保它们拥有自己的转换器实例。

编辑:

在这里,我做了一个小测试项目来演示在带有数据网格的组合框中使用它,它基于默认的 WPF 应用程序 - 只需确保引用 WPF 工具包即可。

这是 Window1.xaml 文件:

<Window 
    x:Class="FlagEnumTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
    xmlns:FlagEnumTest="clr-namespace:FlagEnumTest"
    Title="Window1" Height="300" Width="300">

    <Window.Resources>
        <x:Array Type="{x:Type FlagEnumTest:TestObject}" x:Key="TestArray">
            <FlagEnumTest:TestObject Errors="OpenCondition" />
            <FlagEnumTest:TestObject />
        </x:Array>
    </Window.Resources>

    <StackPanel>

        <Controls:DataGrid ItemsSource="{Binding Source={StaticResource TestArray}}">
            <Controls:DataGrid.Columns>
                <Controls:DataGridTemplateColumn Header="Errors">
                    <Controls:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox>
                                <ComboBox.Resources>
                                    <FlagEnumTest:TestErrorConverter x:Key="ErrorConverter" />
                                </ComboBox.Resources>
                                <CheckBox Content="PowerFailure" IsChecked="{Binding Path=Errors, Converter={StaticResource ErrorConverter}, ConverterParameter={x:Static FlagEnumTest:TestErrors.PowerFailure}}" />
                                <CheckBox Content="OpenCondition" IsChecked="{Binding Path=Errors, Converter={StaticResource ErrorConverter}, ConverterParameter={x:Static FlagEnumTest:TestErrors.OpenCondition}}" />
                            </ComboBox>
                        </DataTemplate>
                    </Controls:DataGridTemplateColumn.CellTemplate>
                </Controls:DataGridTemplateColumn>
            </Controls:DataGrid.Columns>
        </Controls:DataGrid>

    </StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

这是 Window1.xaml.cs 文件的代码隐藏。

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace FlagEnumTest {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window {
        public Window1() {
            InitializeComponent();
        }
    }

    [Flags]
    public enum TestErrors {
        NoError = 0x0,
        PowerFailure = 0x1,
        OpenCondition = 0x2,
    }

    public class TestObject {
        public TestErrors Errors { get; set; }
    } 

    /// <summary>
    /// Provides for two way binding between a TestErrors Flag Enum property and a boolean value.
    /// TODO: make this more generic and add it to the converter dictionary if possible
    /// </summary>
    public class TestErrorConverter : IValueConverter {
        private TestErrors target;

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
            TestErrors mask = (TestErrors)parameter;
            this.target = (TestErrors)value;
            return ((mask & this.target) != 0);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
            this.target ^= (TestErrors)parameter;
            return this.target;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

默认情况下,数据网格将创建自己的列表示形式以及我的强制模板表示形式,因此您可以看到文本表示形式以及复选框表示形式。标志枚举混淆了默认的文本表示,但您仍然可以看到绑定工作正常(选中两个,然后取消选中最后选中的一个 - 字符串值更改为另一个,而不是 0)。