Anirban Paul
Anirban Paul

Reputation: 1165

Validation for DateTime property in viewmodel

I have a DateTime property (say, DateVal) in my viewmodel class and a DatePicker control in View.

    <DatePicker         Grid.Column="1"
                        Width="100"
                        Height="30"
                        SelectedDate="{Binding DateVal,ValidatesOnDataErrors=True}"/>

Problem is that, if the user deletes the date displayed in textbox of Datepicker control ,DateVal property is not changing its value. How can I track that the user has removed the Date displayed in datepicker textbox? regards, Anirban

The Date picker control looks like the following Date picker before editing date picker text box Now if the user just removes the date displayed in date picker text box, the control looks like the following Date picker after editing date picker text box At that point of time value of DateVal is same as before. Only when the user clicks on the calender icon Date is assigned a value null. How can I track the change at the same time when the user makes the text box empty ?

ViewModel Code

public DateTime? DateVal
    {
        get
        {
            return this.dateVal;
        }
        set
        {
            this.dateVal = value;
            this.OnPropertyChanged("DateVal");
        }
    }

xaml code

<DatePicker Name="datePickerDateVal"
                        Grid.Column="1"
                        Width="100"
                        Height="30"
                        SelectedDate="{Binding DateVal,ValidatesOnDataErrors=True}"
                        Text="{Binding DateVal,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}"                          />

I want that the setter property of DateVal must be called when the user clears the Date Picker text box

Upvotes: 1

Views: 3790

Answers (1)

Zoltan
Zoltan

Reputation: 146

The sad news is that the textbox of the DatePicker is set to update its binding source only when it loses focus. The good-ish news is that you can hook into the process via the DatePicker's ControlTemplate:

The XAML:

<DatePicker SelectedDate="{Binding DateVal}" x:Name="__picker" />

And the Code Behind:

DateTime? _dateVal = DateTime.Today;

public Nullable<DateTime> DateVal
{
    get { return _dateVal; }
    set
    {
        if (_dateVal == value)
            return;

        _dateVal = value;
        OnPropertyChanged("DateVal");
    }
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DatePickerTextBox pickerTextBox = __picker.Template.FindName("PART_TextBox", __picker) as DatePickerTextBox;
    if (pickerTextBox == null)
        return;

    pickerTextBox.TextChanged += new TextChangedEventHandler(pickerTextBox_TextChanged);
}

void pickerTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    DatePickerTextBox tb = sender as DatePickerTextBox;

    if (tb == null)
        return;

    if (string.IsNullOrEmpty(tb.Text))
    {
        __picker.SelectedDate = null;
    }
}

I just fiddled around with it and my guess is that the reason you don't get more frequent updates is the circular relation between the text and selected date properties. Making sure that we get updates for null DateTimes should be OK though.

EDIT

Updated the event handler to update the pickers SelectedDate property rather than the property in the view model. This way you can keep the hack entirely within the view while remaining viewmodel agnostic.

Upvotes: 2

Related Questions