views:

1414

answers:

2

Hi,

I want DatePicker to convert the following text pieces to DateTime (shown in international format) so my customers can write a date in DatePickers 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 DatePickers 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 += new RoutedEventHandler(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?

+1  A: 

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.

xamlgeek
I do use a converter. I have tried Text="{Binding Date, Mode=TwoWay, Converter={StaticResource DateConverter}}" and tried it on DisplayDate and SelectedDate which not work because my konverter is string/DateTime. How would you do it?
lasseespeholt
Thanks, I try - 2 secs ;)
lasseespeholt
Hhm, value is DateTime. And if I set Mode=TwoWay I get NotImplementedException and value is also DateTime here. I write in the DatePickers textbox. It does work if it is a TextBox.
lasseespeholt
I just can't get it to work :/ Have you tested it? thanks for helping
lasseespeholt
Works if you add the LostFocus eventhandler - I have updated my sample.
xamlgeek
You are right. It actually does. My date picker is located in a DataGrid and it does not work there. I don't know why. But my initially question is answered. Thank you very much.
lasseespeholt
A: 

I think you might need to actually start will the full control source and customize that. The problem is that the text gets updated in the TextChanged event:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    if (this._textBox != null)
    {
        this.SetValueNoCallback(TextProperty, this._textBox.Text);
    }
}

So by the time you get to your lost focus code, the value has already been set. I was able to get around this using subclassing, but since TextChanged handles every change I'm not sure your parse method will work (Since as soon as you hit 1 number it will get changed to a date).

public class CustomDatePicker : DatePicker
{
    private TextBox textBox; 

    public override void OnApplyTemplate() 
    { 
        base.OnApplyTemplate(); 
        textBox = this.GetTemplateChild("TextBox") as TextBox; 

        if (textBox != null)
            textBox.TextChanged += new TextChangedEventHandler(textBox_TextChanged);
    }

    void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {  
        if (textBox.Text == "now")             
        {                
            //I have also tried with this.SelectedDate/DisplayDate = result;                
            textBox.Text = DateTime.Now.ToShortDateString();                 
        }  
    }
}

It works for me since nothing changes until it spells the whole word, but in your case that probably won't work.

Bryant
No it will not work :/ but thanks anyway. I will for all costs avoid to edit a copy of the template.
lasseespeholt
In your code above you have quote marks around them, are there really quote marks or is that incorrect? Quotes would make it work.
Bryant
Yes it would (I could check when #2 is written) but it is 14032010 I would write in the datepicker.
lasseespeholt