title: How can you two-way bind a checkbox to an individual bit of a flags enumeration?
body: <p>For those who like a good WPF binding challenge:</p>
  
  <p>I have a nearly functional example of two-way binding a <code>CheckBox</code> to an individual bit of a flags enumeration (thanks Ian Oakes, <a href="http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c05b7e7e-25cd-4a41-8bf5-e35d2caff797/" rel="nofollow noreferrer">original MSDN post</a>).  The problem though is that the binding behaves as if it is one way (UI to <code>DataContext</code>, not vice versa). So effectively the <code>CheckBox</code> does not initialize, but if it is toggled the data source is correctly updated. Attached is the class defining some attached dependency properties to enable the bit-based binding. What I've noticed is that ValueChanged is never called, even when I force the <code>DataContext</code> to change.</p>
  
  <p><strong>What I've tried:</strong> Changing the order of property definitions, Using a label and text box to confirm the <code>DataContext</code> is bubbling out updates, Any plausible <code>FrameworkMetadataPropertyOptions</code> (<code>AffectsRender</code>, <code>BindsTwoWayByDefault</code>), Explicitly setting <code>Binding Mode=TwoWay</code>, Beating head on wall, Changing <code>ValueProperty</code> to <code>EnumValueProperty</code> in case of conflict.</p>
  
  <p>Any suggestions or ideas would be extremely appreciated, thanks for anything you can offer!</p>
  
  <p>The enumeration:</p>
  
  <pre><code>[Flags]
  public enum Department : byte
  {
      None = 0x00,
      A = 0x01,
      B = 0x02,
      C = 0x04,
      D = 0x08
  } // end enum Department
  </code></pre>
  
  <p>The XAML usage:</p>
  
  <pre><code>CheckBox Name="studentIsInDeptACheckBox"
           ctrl:CheckBoxFlagsBehaviour.Mask="{x:Static c:Department.A}"
           ctrl:CheckBoxFlagsBehaviour.IsChecked="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}"
           ctrl:CheckBoxFlagsBehaviour.Value="{Binding Department}"
  </code></pre>
  
  <p>The class:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// A helper class for providing bit-wise binding.
  /// &lt;/summary&gt;
  public class CheckBoxFlagsBehaviour
  {
      private static bool isValueChanging;
  
      public static Enum GetMask(DependencyObject obj)
      {
          return (Enum)obj.GetValue(MaskProperty);
      } // end GetMask
  
      public static void SetMask(DependencyObject obj, Enum value)
      {
          obj.SetValue(MaskProperty, value);
      } // end SetMask
  
      public static readonly DependencyProperty MaskProperty =
          DependencyProperty.RegisterAttached("Mask", typeof(Enum),
          typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(null));
  
      public static Enum GetValue(DependencyObject obj)
      {
          return (Enum)obj.GetValue(ValueProperty);
      } // end GetValue
  
      public static void SetValue(DependencyObject obj, Enum value)
      {
          obj.SetValue(ValueProperty, value);
      } // end SetValue
  
      public static readonly DependencyProperty ValueProperty =
          DependencyProperty.RegisterAttached("Value", typeof(Enum),
          typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(null, ValueChanged));
  
      private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
          isValueChanging = true;
          byte mask = Convert.ToByte(GetMask(d));
          byte value = Convert.ToByte(e.NewValue);
  
          BindingExpression exp = BindingOperations.GetBindingExpression(d, IsCheckedProperty);
          object dataItem = GetUnderlyingDataItem(exp.DataItem);
          PropertyInfo pi = dataItem.GetType().GetProperty(exp.ParentBinding.Path.Path);
          pi.SetValue(dataItem, (value &amp; mask) != 0, null);
  
          ((CheckBox)d).IsChecked = (value &amp; mask) != 0;
          isValueChanging = false;
      } // end ValueChanged
  
      public static bool? GetIsChecked(DependencyObject obj)
      {
          return (bool?)obj.GetValue(IsCheckedProperty);
      } // end GetIsChecked
  
      public static void SetIsChecked(DependencyObject obj, bool? value)
      {
          obj.SetValue(IsCheckedProperty, value);
      } // end SetIsChecked
  
      public static readonly DependencyProperty IsCheckedProperty =
          DependencyProperty.RegisterAttached("IsChecked", typeof(bool?),
          typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(false, IsCheckedChanged));
  
      private static void IsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
          if (isValueChanging) return;
  
          bool? isChecked = (bool?)e.NewValue;
          if (isChecked != null)
          {
              BindingExpression exp = BindingOperations.GetBindingExpression(d, ValueProperty);
              object dataItem = GetUnderlyingDataItem(exp.DataItem);
              PropertyInfo pi = dataItem.GetType().GetProperty(exp.ParentBinding.Path.Path);
  
              byte mask = Convert.ToByte(GetMask(d));
              byte value = Convert.ToByte(pi.GetValue(dataItem, null));
  
              if (isChecked.Value)
              {
                  if ((value &amp; mask) == 0)
                  {
                      value = (byte)(value + mask);
                  }
              }
              else
              {
                  if ((value &amp; mask) != 0)
                  {
                      value = (byte)(value - mask);
                  }
              }
  
              pi.SetValue(dataItem, value, null);
          }
      } // end IsCheckedChanged
  
      /// &lt;summary&gt;
      /// Gets the underlying data item from an object.
      /// &lt;/summary&gt;
      /// &lt;param name="o"&gt;The object to examine.&lt;/param&gt;
      /// &lt;returns&gt;The underlying data item if appropriate, or the object passed in.&lt;/returns&gt;
      private static object GetUnderlyingDataItem(object o)
      {
          return o is DataRowView ? ((DataRowView)o).Row : o;
      } // end GetUnderlyingDataItem
  } // end class CheckBoxFlagsBehaviour
  </code></pre>