Search code examples
silverlightdatetimedatepickervalueconverterlostfocus

Intercept Silverlight DatePicker's convert from text to DateTime


I want DatePicker to convert the following text pieces to DateTime (shown in international format) so my customers can write a date in DatePicker textbox faster so it is not just DateTime.Parse I will use:

"3" to 2009-10-03
"14" to 2009-10-14
"1403" to 2009-03-14
"140310" to 2010-03-14
"14032010" to 2010-03-14

I have tried different methods to do it but they do not work. I have tried to bind DatePicker.Text/DatePicker.SelectedDate/DatePicker.DisplayDate with a custom valueconverter. But it do not work because DatePicker already have processed the text before I get to the text.

I have also tried to convert in the DatePicker TextBox.LostFocus like this:

public class CustomDatePicker : DatePicker
{
    private DatePickerTextBox textBox;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        textBox = this.GetTemplateChild("TextBox") as DatePickerTextBox;

        if (textBox != null)
            textBox.LostFocus += textBox_LostFocus;
    }

    void textBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (textBox == null) return;

        DateTime result;

        // This is my method for converting my special cases, 
        // parses d, dd, mm, ddmm, ddmmyy, ddmmyyyy
        if (textBox.Text.TryParseShortcut(out result)) 
        {
            // I have also tried with 
            // this.SelectedDate/DisplayDate = result;
            textBox.Text = result.ToString("dd/MM/yyyy"); 
            return;
        }

        if (DateTime.TryParse(textBox.Text, out result))
        {
            // I have also tried with 
            // this.SelectedDate/DisplayDate = result;
            textBox.Text = result.ToString("dd/MM/yyyy");
            return; 
        }
    }
}

Any ideas?


Solution

  • If you use Binding to bind data to your DatePicker, you could use a ValueConverter.

    Quick example of date converter:

    public class CustomDateValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is string)
            {
                string dateValue = (string)value;
                switch (dateValue.Length)
                {
                    case 1:
                    case 2:
                        return new DateTime(DateTime.Now.Year, DateTime.Now.Month, System.Convert.ToInt32(dateValue)).ToString("dd/MM/yyyy");
                    //...
                }
            }
    
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            // here you should implement your logic to convert your value back.
    
            return value;
        }
    }
    

    DatePickerTextBox control in XAML:

    <controls:DatePickerTextBox Text="{Binding Path=Data, Mode=TwoWay, Converter={StaticResource CustomDateValueConverter}}" />
    

    DatePickerTextBox in cs:

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            DataContext = new MyData() { Data = "3" };
    
            _textBox.LostFocus += (se, ea) =>
                {
                    _textBox.DataContext = 
                        new MyData() { Data = _textBox.Text };
                };
    }
    
    public class MyData
    {
        public string Data { get; set; }
    }
    

    I have just made a class called MyData to use as data in this sample.