views:

3436

answers:

1

For some reason I'm having issues Binding a custom User Control up through my ViewModel in an MVVM WPF application. The basic control is a Date entry form with three text boxes. I am using the codebehind for the usercontrol to capture the textchange event and so some manipulation. For some reason Adding Binding to the property never triggers.

XAML of user Control:

<UserControl x:Class="MYLibray.DateBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="800">
<StackPanel>

    <Border CornerRadius="10" Height="200" BorderBrush="Gray" Background="Gray">
 <StackPanel Orientation="Horizontal" OpacityMask="{x:Null}" HorizontalAlignment="Center">
 <TextBox Name="txtMonth" Height="100" Width="90" BorderThickness="0,0,0,5" Background="{x:Null}" Text="" FontSize="72" TextChanged="TextChanged">
  <TextBox.BorderBrush>
   <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FF000000" Offset="0"/>
    <GradientStop Color="#FF000000" Offset="1"/>
   </LinearGradientBrush>
  </TextBox.BorderBrush>
 </TextBox>
            <TextBlock Text="/" FontSize="72" Height="100" Width="50" />
            <TextBox x:Name="txtDay" Height="100" Width="90" Background="{x:Null}" BorderThickness="0,0,0,5" VerticalAlignment="Stretch" FontSize="72" TextChanged="TextChanged">
                <TextBox.BorderBrush>
                 <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                  <GradientStop Color="#FF000000" Offset="0"/>
                  <GradientStop Color="#FF000000" Offset="1"/>
                 </LinearGradientBrush>
                </TextBox.BorderBrush>
            </TextBox>
            <TextBlock Text="/19" FontSize="72" Height="100" Width="Auto" />
            <TextBox x:Name="txtYear" Height="100" Width="90" Background="{x:Null}" BorderThickness="0,0,0,5"  FontSize="72" TextChanged="TextChanged">
                <TextBox.BorderBrush>
                 <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                  <GradientStop Color="#FF000000" Offset="0"/>
                  <GradientStop Color="#FF000000" Offset="1"/>
                 </LinearGradientBrush>
                </TextBox.BorderBrush>
            </TextBox>
 </StackPanel>
 </Border>

</StackPanel>

CodeBehind:

public partial class DateBox : UserControl

{

  private string _date = "";
  public static DependencyProperty TextProperty = DependencyProperty.RegisterAttached("DateText", typeof(string), typeof(DateBox), new PropertyMetadata(TextPropertyChanged));
  public static DependencyProperty EnabledProperty = DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(DateBox), null);

  public DateBox()
  {                                 
     InitializeComponent();
     this.DataContext = this;
     txtMonth.Focus();


  }

  public bool Enabled
  {
     get
     {
        return (bool)GetValue(DateBox.EnabledProperty);
     }
     set
     {
        SetValue(DateBox.EnabledProperty, value);

        txtDay.IsEnabled = value;
        txtMonth.IsEnabled = value;
        txtYear.IsEnabled = value;
     }
  }

  public string DateText
  {
     get
     {
        return (string)this.GetValue(TextProperty);
     }
     set
     {
        this.SetValue(TextProperty, value);



     }
  }



  static void TextPropertyChanged(DependencyObject property,DependencyPropertyChangedEventArgs args)
  {
     ((DateBox)property).OnTextPropertyChanged((object)args.NewValue);
  }

  private void OnTextPropertyChanged(object newValue)
  {
     _date = newValue.ToString();
     this.UpdateLayout();
     DateTime d;
     if (DateTime.TryParse(_date, out d))
     {
        txtDay.Text = d.Day.ToString();
        txtMonth.Text = d.Month.ToString();
        txtYear.Text = (d.Year - 1900).ToString();
     }
     else
     {
        txtDay.Text = "";
        txtMonth.Text = "";
        txtYear.Text = "";
     }

     DateText = d.ToShortDateString();
  }

  bool AreAllValidNumericChars(string str)
  {
     bool ret = true;
     if (str == System.Globalization.NumberFormatInfo.CurrentInfo.PositiveSign)
     {
        return ret;
     }
     int l = str.Length;
     for (int i = 0; i < l; i++)
     {
        char ch = str[i];
        ret &= Char.IsDigit(ch);
     }

     return ret;
  }



  private void TextChanged(object sender, TextChangedEventArgs e)
  {

     TextBox txt = (TextBox)sender;

     switch (txt.Name)
     {
        case "txtMonth":
           if (txt.Text.Length == 1)
           {
              if (Convert.ToInt32(txt.Text) > 1)
              {
                 string value = txt.Text;
                 txt.Text = "0" + value;
                 txtDay.Focus();
              }
           }
           if (txt.Text.Length == 2)
           {
              txtDay.Focus();
           }
           break;
        case "txtDay":
           if (txt.Text.Length == 1)
           {
              if (Convert.ToInt32(txt.Text) > 3)
              {
                 string value = txt.Text;
                 txt.Text = "0" + value;
                 txtYear.Focus();
              }
           }
           if (txt.Text.Length == 2)
           {
              txtYear.Focus();
           }
           break;

        case "txtYear":
           if (txt.Text.Length == 2)
           {
              DateTime d;
              string datestring = txtMonth.Text + "/" + txtDay.Text + "/19" + txtYear.Text;
              if (DateTime.TryParse(datestring,out d))
              {
                 DateText = d.ToShortDateString();
              }
           }
           break;
        default:
           break;
     }




  }

}

When I create the usercontrol in the DataTemplate like so:

<uc:DateBox DateText="{Binding BirthDate}" />

The get and set of BirthDate in my ViewModel never get set. BirthDate on the VM is a String.

+6  A: 

Check the DataContext of the control and of the parent.

to help with debugging your bindings, check out Bea Stollnitz's blog

basically, add this xmlns to your control

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

then add this to your Binding(s)

{Binding ....    , diagnostics:PresentationTraceSources.TraceLevel=High }
Muad'Dib
Thank you. The DataContext of the UserControl was my issue.
cjibo