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.
Check the
DataContextof the control and of the parent.to help with debugging your bindings, check out Bea Stollnitz’s blog
basically, add this
xmlnsto your controlthen add this to your
Binding(s)