I feel a trend starting… another http://stackoverflow.com/ answer, here’s the question (massively snipped):
I have a nearly functional example of two-way binding a checkbox to an individual bit of a flags enumeration… The problem though is that the binding behaves as if it is one way (UI to DataContext, not vice versa). So effectively the check box does not initialize, but if it is toggled the data source is correctly updated…
Here’s the full link to the post for more context, if required.
The bottom line is that a solution to binding to “bit” flags can be challenging, but the solution initially offered in the question was extremely complex (class with a bunch of Attached Properties yadda, yadda, yadda), when I looked at it thought, I thought "surely that can be done with a value converter”; after a little bit of hacking I have a simple IValueConverter implementation for any flags enumeration.
But first, consider the following Enum definition:
[Flags]
public enum Department
{
None = 0,
A = 1,
B = 2,
C = 4,
D = 8
}
My first step was to create a specific converter for the Department Enum:
public class DepartmentValueConverter : IValueConverter
{
private Department target;
public DepartmentValueConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Department mask = (Department)parameter;
this.target = (Department)value;
return ((mask & this.target) != 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
this.target ^= (Department)parameter;
return this.target;
}
}
The tricky part, according to the initial question, was the ConvertBack implementation. The solution here is to simply store the incoming value in the Convert method, and when the value is changed the ConvertBack method uses the Exclusive-Or assignment operator to toggle the bit, which works lovely.
However, I also figured that it should be possible to create a generic version of this converter – this type of converter is not something that you’d be creating everyday, so to have a specific version for each Flags Enum would probably be a totally acceptable solution… but… this is what I came up with:
public class FlagsEnumValueConverter : IValueConverter
{
private int targetValue;
public FlagsEnumValueConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int mask = (int)parameter;
this.targetValue = (int)value;
return ((mask & this.targetValue) != 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
this.targetValue ^= (int)parameter;
return Enum.Parse(targetType, this.targetValue.ToString());
}
}
So the key to this solution is that it works with the underlying type for most Enum values: Int32. The basic pattern is the same, but it simply replaces the specific Enum value with an Int32; with the only tricky part being in the ConvertBack: When I simply returned an Int32, when an Enum value was expected, WPF did not update the underlying value in the binding. I found I had to convert the Int32 to the specific Enum value represented by the Int32; which I simply handled by using the Enum.Parse method.
The following screenshot then shows how to consume the converter in XAML. Note that the mask value for the Enum value instance is passed in the CommandParameter property on the binding declaration.
I have uploaded a sample application here:
Here’s a screenshot of the app, for what it’s worth given its simplicity :)
Comments and questions welcome as always.