@virtualolympus posted a great bitwise enum binding solution in response to my sateful-converter-hack and it looks like a really nice clean solution. If you’re a WPF/XAML developer, definitely check it out.

When you find yourself writing entire helper classes – or worse – implementing hacks, it’s time to admit that XAML / MVVM needs better Enum support!  Until then @virtualolympus‘ solution is the best I’ve seen.

Ok, I admit it – I did work out another hack for this problem this morning :D  Hack hack hack! If you’re stuck on a pre-dynamic framework and still left wondering how to easily bind to a bitwise flag, this might actually be viable.

First examine these CheckBox bindings and note the ConverterParameter:

<CheckBox IsChecked="{Binding EditingSpecies.Flags, Converter={StaticResource BitwiseToBool}, ConverterParameter=1|A}" Content="BreathesAir"/>
<CheckBox IsChecked="{Binding EditingSpecies.Flags, Converter={StaticResource BitwiseToBool}, ConverterParameter=2|A}" Content="BreathesWater"/>

We’re supplying two values to the Converter, separated by pipe. The first value is of the bit flipped by this CheckBox; the other value is a “group” name. You can call the group whatever you want (“A” was arbitrary) so long as the same group name is used on all CheckBoxes flipping bits for a Flag.

The Converter uses the contextual group name to maintain the state (value) of the bitwise Flag without tainting the converter with too much inappropriate context. The result is a more generic/versatile/orthogonal bitwise Converter:

public class BitwiseToBool : IValueConverter
{
	Dictionary<string, Int64> EnumStates = new Dictionary<string, Int64>();

	public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		string[] parms = parameter.ToString().Split('|');

		Int64 flipbit = Int64.Parse(parms[0]);

		//statekey = parms[1]

		Int64 enumvalue = System.Convert.ToInt64(value);

		if (!this.EnumStates.ContainsKey(parms[1]))
			this.EnumStates.Add(parms[1], enumvalue);
		else
			this.EnumStates[parms[1]] = enumvalue;

		return (enumvalue & flipbit) != 0;
	}

	public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
	{
		string[] parms = parameter.ToString().Split('|');

		Int64 flipbit = Int64.Parse(parms[0]);

		//statekey = parms[1]

		Int64 enumvalue = this.EnumStates[parms[1]];

		if ((bool)value)
			enumvalue |= flipbit;
		else
			enumvalue &= ~flipbit;

		this.EnumStates[parms[1]] = enumvalue;

		return Enum.Parse(targetType, enumvalue.ToString());
	}
}

But it has 2 design faux pas:

  1. It requires knowledge of ConverterParameter “hidden magic”, i.e. keying the ConverterParameter with a group name.
  2. It somewhat technically violates SPOT/DRY. The Flag value on both the VM and in the Converter need to remain reliably synchronized.

So that now gives us 2 dubious-but-simple ways to bind to a bitwise enum, plus 1 really-good-but-requires-dynamicobjects way.  Programming is fun!

Today I finally found the GetChangeSet problem: I failed to new-up an EntitySet… that’s all it was (at least it was an easy fix).

With that, Species are in! This thing is almost done! Just need to add Compounds & Elements.  Share in my Database editing joy…

Bonus content! The Arsanth Database Editor theme song!