Tutorial :WPF MVVM + UserControl with Code Behind



Question:

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.


Solution:1

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 }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »