Introduction
A flag enumeration is a very useful tool in programming. However, it is not straightforward to use flags in binding. Somehow or another,
the particular flag has to be specified. This is possible using the binding "parameter". With this information, it is quite straightforward to convert for the View, but
the problem is converting back. You would normally be binding to a checkbox and this value is either true or false (tri-state does not make sense).
When converting back, there is no information about the state of the other flags. Without this information, it is not possible to update the flags value in the View-Model.
This is one of the main reasons a special class is needed to support binding a set of flags to a View. Once there is an implementation to
support flags in both WPF and Silverlight, implementations can be much cleaner.
Description
When I develop WPF (or Silverlight) applications, I like to minimize the properties I need in the View-Model to support the View, and so
have often used Value Converters to determine if a value is null and convert this to a Boolean or Visibility property to enable or hide controls. I also
like to use a state enumeration with a Value Converter to change the look of the UI. I also will have a state enumeration and then use the state name in the
parameter when binding to the state enumeration instance.
I had a case where I had a checkbox collection that could be enabled or disabled. When multiple (enabled) checkboxes were selected, there
would be lines with arrowheads and the lines would connect adjacent checkboxes and checkboxes separated by unchecked checkboxes. A graphic was associated to the
left of each checkbox. The graphic consisted of two quarter circles, one curving from the left up, and the other curving left down from the same
starting point. There was an arrow head pointing left, with its tip being at the starting point of both curves. Then there was a line the connected the separated
ends of the two quarter circles. By hiding or showing each of these graphic elements, it was possible to connect all the checkboxes together, with lines
ending in an arrowhead. I wanted a clean way to implement this UI.
I used two integers with a bit representing each checkbox and the associated graphic. One integer was used to control if each checkbox was enabled; the other indicated
the checkboxes' checked state. This second integer was used to control the graphics. To do the binding, the Parameter attribute of the binding was used, each
CheckBox and associated graphic using a specific integer for all bindings. The graphic would be bound to the integer value that indicates the checked states
for all checkboxes, and thus could determine if the associated CheckBox was checked, and if it was associated with the maximum or minimum value checkbox,
or if it was outside the maximum and minimum (arrowheads either went up or down, not both). Check the code for the graphic in the example to get the details of how this was done.
Originally, I created a lot of inline code, but knew this was not the perfect solution. A better solution was to create a class that encapsulated all of this functionality.

As an example of using a flag enumeration that was bound to a checkbox collection, I used two checkbox collections, the first to enable or disable
a checkbox in the second collection. Setting a particular checkbox would enable checkbox in a collection that was in a mirror of the first checkbox collection.
This second checkbox would set a value on another flag enumeration that would control a graphic. The graphic was bound to the same flag enumeration as the second checkbox
collection to get the graphic to correctly connect the second checkbox collection. (Note: I have included a graphic associated with the first checkbox collection to show binding using
the Value property of the BindingFlags class to show how I initially solved the problem, and the code is in the Graphics class to support binding to the
Value property instead of an instance of the BindingFlags class.)
As implemented, I use an unsigned integer to store the flags. This will support 32 flags, which should satisfy most scenarios;
a short integer would not meet more cases and would not have provided much benefit in processing or memory.
For the functionality, I needed to calculate information about the flags as a whole: the minimum set flag value and the maximum set flag
value. There are some efficient ways of calculating attributes of bits in an integer, but the algorithms are not obvious. This is a reason for encapsulating
the functionality in a class. I implemented the functions as properties so that they can be used directly for binding. This also has another benefit in that
the bindings for these functions will be updated when the PropertyChanged event for the instance of the BindingFlags class is raised. Some of the somewhat
costly processing flag functions I needed and wanted to be efficient was calculating the count of set flags, the maximum flag value, and the minimum flag value:
public int Count
{
get
{
int count = 0;
uint n = (uint)flags;
while (n != 0)
{
count++;
n &= (n - 1);
}
return count;
}
}
public int Max
{
get
{
if (flags == 0) return -1;
uint v = (uint)flags;
int result = 0;
for (int i = 4; i >= 0; i--) {
if ((v & MaxFunctionFlagsMasks[i]) > 0)
{
v >>= MaxMinFunctionBitShiftArray[i];
result |= MaxMinFunctionBitShiftArray[i];
}
}
return result;
}
}
public int Min
{
get
{
if (flags == 0) return -1;
uint v = (uint)flags;
int result = 0;
for (int i = 4; i >= 0; i--) {
if ((v & MinFunctionFlagsMasks[i]) == 0)
{
v >>= MaxMinFunctionBitShiftArray[i];
result |= MaxMinFunctionBitShiftArray[i];
}
}
return result;
}
}
private static uint[] MaxFunctionFlagsMasks = { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000 };
private static int[] MaxMinFunctionBitShiftArray = { 1, 2, 4, 8, 16 };
private static uint[] MinFunctionFlagsMasks = { 0x1, 0x3, 0xF, 0xFF, 0x0000FFFF };
I incorporated the IValueConverter functionality within the same class just to keep all the code together, and to eliminate the need to
have more exposed variables. There are several variables inside the BindingFlags class that are used specifically for the IValueConverter, and
there is a constructor to support the IValueConverter that is private so can only be used by the class. There is obviously a cost of memory for using the
same class for two functions, and maybe people who use the class may want to break out the IValueConverter code. The IValueConverter takes a parameter which
is the flag number, with flag representing the least significant bit being ‘0’, and the flag for the most significant bit being ‘31’. When converting to a bool
for the flag, just use the parameter as the flag index, and return a bool to indicate if the flag is set. When converting back, a BindingFlags instance
is created using a special constructor that sets a flag to indicate that this is a special instance of BindingFlags. Then using the DependencyPropertyUpdate
in a BindingFlags property in the ViewModel, the DependencyPropertyUpdate method uses the flag value to indicate which flag (could be multiple flags,
but this feature is not used) is changed. Another feature of the IValueConverter code is that the returned true and false values can be specified when
the IValueConverter is declared in the XAML. The default is a bool true and false, respectively. Note: that only the
TrueValue is checked in the IValueConverter code, and, if so, both TrueValue and FalseValue are set to the defaults.
In the example, I use this feature to pass either Visibility.Collapsed or Visibility.Visible using
the instance that is labeled FlagVisibilityConverter.
The following is the IValueConverter code:
#region IValueConverter
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (TrueValue == null)
{
TrueValue = true;
FalseValue = false;
}
BindingFlags f = value as BindingFlags;
int p;
if (f != null & int.TryParse(parameter.ToString(), out p))
{
return (f[p] ? TrueValue : FalseValue);
}
return FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
int p;
if (value is bool && int.TryParse(parameter.ToString(), out p))
{
return new BindingFlags(p, (bool)value);
}
return new BindingFlags();
}
public object TrueValue { get; set; }
public object FalseValue { get; set; }
#endregion
When creating a BindingFlags class property for binding, the following code is used:
public BindingFlags Flags
{
get { return _Flags; }
set
{
if (value.DependencyPropertyUpdate(ref _Flags))
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Flags"));
}
}
}
}
private BindingFlags _GraphicFlags;
The DependencyPropertyUpdate method takes a single reference argument of BindingFlags. This has to be a reference argument so that the
instance of BindingFlags can be changed. This is required to force the bindings to update. If just a field or property in BindingFlags is updated, then there
would be no change event triggered because the code does not recognize that there has been a change in the variable (Microsoft, it would be nice if
changing the GetHashCode() return value would force a binding recalculate). Also, I ensure that neither of the two BindingFlags instances is changed by
this method. The bool return value is used to check if the PropertyChanged event should be triggered.
The following is the code used to update a flag value with a return type of bool, which is true if any of the flags were changed:
public bool DependencyPropertyUpdate(ref BindingFlags f)
{
if (isSpecialInstance)
{
uint localFlag;
if (isSpecialInstanceSet)
localFlag = flags | f.flags;
else
localFlag = f.flags & (flags ^ (uint)0xFFFFFFFF);
if (localFlag == f.flags)
return false;
f = new BindingFlags(localFlag);
return true;
}
else
{
BindingFlags orgFlag = f;
f = this;
return flags != orgFlag.flags;
}
}
Notice in this method the checking of the field isSpecialInstance; if a special bool is set to indicate that the value in the flags field is
to be used to set or reset the bits set in that flags field, the new BindingFlags value is ORed with the current flag (this will force the specified flag to be
set); otherwise, the BindingFlags value is exclusive ORed with all ones and then ANDed with the flag value flag (this will force the specified flag to be
reset). If the isSpecialInstanceSet bool is true, then the bits are set, otherwise the bits are reset.
Inside the example, I attempted to show a number of ways that the binding could be used in addition to enabling and setting checkboxes, and
controlling the graphic. I used it to make TextBlocks visible when the associated checkbox was checked. Hopefully this pattern will be of use to others.
I also created a special Masked method in the BindingFlags class to apply a mask, which was also a BindingFlags instance, to the flags
field, and return the result as a BindingFlags class. I needed some function to reset checkboxes in the second set when the corresponding checkbox was
not set in the first set. All I needed to do was to use this to set the BindingFlags instance controlling the graphics when there was a change in the
BindingFlags instance controlling the first set of checkboxes. The method returns an instance of
BindingFlags since I have to create a new instance of BindingFlags to ensure the binding recognized that there had been a change.
public BindingFlags ControlFlags
{
get { return _ControlFlags; }
set
{
if (value.DependencyPropertyUpdate(ref _ControlFlags))
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ControlFlags"));
}
GraphicFlags = GraphicFlags.Masked(ControlFlags);
}
}
}
Points of Interest
I had a lot of trouble getting the binding to a property of BindingFlags to work. After fixing a couple of bugs, I managed to convince myself that the code worked
by binding to the Value property. The code worked perfectly with this change in the View, but I thought was not too intuitive, and required some funny code in the class
that created the graphic. I went back and made some changes, including setting a couple of the flags true initially, and discovered that the binding to an instance of the class
was working, just the triggering the change logic was not. I attempted to just add the INotifyPropertyChanged interface, and raising PropertyChanged
events inside the class, but that did not work. Also attempted to override Equals and GetHashCode; this also did not work. Inheriting from
DependenyProperty and DependencyObject did not work either. It was only after a lot of frustrations that I finally figured out that what
was needed to be done in the binding was creating a new instance of the BindingFlags class when there is a change in the value.
I had another issue that I had to give thought to get working. I wanted to use the flags that enabled the second set of flags to ensure that a checkbox in the second set
was unchecked if it was disabled. I was able to accomplish this by using a MultiValueConverter, but the problem was that there was no way to convert back since again
I did not have the first set of flags. Thus I was able to force a checkbox not to be set if the checkbox was disabled, but could not get the controlling
BindingFlags instance to update to correspond to the state of the checkbox, and thus the graphic would be in the wrong state. Also, of course,
the BindingFlags instance would be wrong. This could have been fixed by using the same multi-binding as the checkboxes, but the bound BindingFlags
instance would be wrong. This is why I created the Masked method.
Summary
This solution is far from perfect, mostly because of the method of binding from the View to the View-Model requiring different code from normal binding, but it is not particularly
more difficult than binding with a value type or string. Also, there is the need to create an new instance of the BindingFlags class when its value is changed.
The implementation requires an unusual value converter, using an instance of the BindingFlags class in a different way than normal.
Still, I do not believe that these issues are significant, and the class is an effective tool to more cleanly implement solutions in XAML binding.
Help: The graphic I use does not resize the way I would like. If somebody has a solution, I would appreciate it.