title: Custom control made of radio buttons not checking radio button if data binding is same as default
body: <p>I created a custom control, which is simply three radio buttons, and an <code>Answer</code> property of type <code>string</code> that can be one of <code>"Yes"</code>, <code>"No"</code>, or <code>"N/A"</code>. Clicking the radio buttons changes the <code>Answer</code> property, or changing the <code>Answer</code> property should change which radio button is selected. <code>Answer</code> is implemented as a DependancyProperty so I can perform data binding with it (the source is a property of an EF4 entity).</p>
  
  <p>It all works well and good, except in one particular situation - when the value of the column in the database matches the default specified in the <code>DependencyProperty.Register()</code> call. In this case, the control is displayed without <em>any</em> radio button checked!</p>
  
  <p>I've turned off the option for the debugger to step over property setters, and I know that <code>SetChecks</code>() is being called and supposedly setting the <code>IsChecked</code> property of the radio button to true.</p>
  
  <p>If I change the default of the property, that becomes the value that is not checked... <code>MyId</code> was put in place just to identify the specific control I'm looking at in the debugger, since I have multiple of these controls in my view.</p>
  
  <p>First the <code>.cs</code> code:</p>
  
  <pre><code>public partial class YesNoNotApplicableRadio : UserControl, INotifyPropertyChanged {
      public string MyId {
          get;
          set;
      }
  
      public static readonly DependencyProperty AnswerProperty = DependencyProperty.Register(
          "Answer",
          typeof(string),
          typeof(YesNoNotApplicableRadio),
          new FrameworkPropertyMetadata("N/A",
              FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
              new PropertyChangedCallback(AnswerPropertyChanged),
              new CoerceValueCallback(CoerceAnswer)
              ),
          new ValidateValueCallback(ValidateAnswer)
          );
  
      public static bool ValidateAnswer(Object value) {
          string s = value as string;
          if (s == null)
              return true;
          s = s.Trim().ToUpper();
          if (s.Equals("YES") || s.Equals("NO") || s.Equals("N/A") || s.Equals(""))
              return true;
          return false;
      }
  
      public static void AnswerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
          YesNoNotApplicableRadio o = d as YesNoNotApplicableRadio;
          string val = (string)e.NewValue;
          SetChecks(o, val.Trim().ToUpper());
      }
  
      private static void SetChecks(YesNoNotApplicableRadio selector, string val) {
          selector.YesRadio.IsChecked = false;
          selector.NoRadio.IsChecked = false;
          selector.NaRadio.IsChecked = false;
          if (val.Equals("YES"))
              selector.YesRadio.IsChecked = true;
          else if (val.Equals("NO"))
              selector.NoRadio.IsChecked = true;
          else if (val.Equals("N/A") || val.Equals(""))
              selector.NaRadio.IsChecked = true;
      }
  
      private void Radio_Click(object sender, RoutedEventArgs e) {
          if ((bool)YesRadio.IsChecked)
              Answer = "Yes";
          else if ((bool)NoRadio.IsChecked)
              Answer = "No";
          else
              Answer = "N/A";
      }
  
      public static Object CoerceAnswer(DependencyObject d, Object baseValue) {
          YesNoNotApplicableRadio o = (YesNoNotApplicableRadio)d;
          string s = baseValue as string;
          if (s == null)
              return ("N/A");
          else
              return (s);
      }
  
      public string Answer {
          get { return ((string)GetValue(AnswerProperty)); }
          set { SetValue(AnswerProperty, value); NotifyPropertyChanged("Answer"); }
      }
  
      public YesNoNotApplicableRadio() {
          InitializeComponent();
          Guid groupGuid = System.Guid.NewGuid();
          YesRadio.GroupName = groupGuid.ToString();
          NoRadio.GroupName = groupGuid.ToString();
          NaRadio.GroupName = groupGuid.ToString();
  
      }
  
      public event PropertyChangedEventHandler PropertyChanged;
  
      private void NotifyPropertyChanged(string name) {
          if (PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs(name));
      }
  }
  </code></pre>
  
  <p>Here is the <code>.xaml</code>:</p>
  
  <pre><code>&lt;UserControl x:Class="RovingAuditEntry.Controls.YesNoNotApplicableRadio"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
               mc:Ignorable="d"
               d:DesignHeight="30" d:DesignWidth="130"&gt;
      &lt;StackPanel Orientation="Horizontal" Margin="5"&gt;
          &lt;RadioButton Content="Yes" Height="16" Name="YesRadio" Click="Radio_Click" /&gt;
          &lt;RadioButton Content="No" Height="16" Name="NoRadio" Margin="5,0,0,0" Click="Radio_Click" /&gt;
          &lt;RadioButton Content="N/A" Height="16" Name="NaRadio" Margin="5,0,0,0" Click="Radio_Click" /&gt;
      &lt;/StackPanel&gt;
  &lt;/UserControl&gt;
  </code></pre>