У меня есть способ, который может работать. Я не возьму на себя ответственность за это - я нашел этот метод в Интернете и забыл сохранить адрес.
В моем проекте мне нужно было привязать несколько флажков к перечислению флага. Чтобы помочь, я нашел реализацию простого преобразователя значений для облегчения двухстороннего связывания. Он не является универсальным, и один экземпляр конвертера может работать только с одной целью (то есть с одним экземпляром значения и его группой флажков) за раз. Преобразователь использует сохраненную ссылку на значение как способ обратного преобразования, поэтому, если вы попытаетесь использовать его повторно между отдельными экземплярами объекта, он не будет работать. Тем не менее, это единственное использование, которое я имел для чего-то подобного, и это работало как шарм.
Конвертер:
/// <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;
}
}
В 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}...
В вашем случае вы можете поместить это в шаблон ячейки данных (хотя, очевидно, вы, вероятно, предпочтете использовать более широкий список, а не простую стековую панель. Обязательно создайте экземпляр конвертера рядом с контейнером группы флажков, чтобы у них был свой экземпляр преобразователя.
Edit:
Здесь я сделал небольшой тестовый проект, чтобы продемонстрировать, как использовать его в комбинированном окне с сеткой данных, он основан на приложении 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>
А вот код файла 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;
}
}
}
По умолчанию сетка данных создаст свое собственное представление столбца, а также мое шаблонное представление, так что вы можете увидеть текстовое представление, а также флажок. Флаг enum сбивает с толку текстовое представление по умолчанию, но вы все равно можете видеть, что привязка работает правильно (отметьте оба, затем снимите флажок с того, который вы проверяли последним - строковое значение меняется на другое, а не 0).