Pergunta

Eu quero DatePicker para converter os seguintes pedaços de texto para DateTime (mostrado no formato internacional) para que meus clientes podem escrever uma data na caixa de texto DatePicker mais rápido por isso não é apenas DateTime.Parse vou usar:

"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

Eu tentei diferentes métodos para fazer isso, mas eles não funcionam. Tentei ligam DatePicker.Text / DatePicker.SelectedDate / DatePicker.DisplayDate com um ValueConverter personalizado. Mas isso não funciona porque DatePicker já ter processado o texto antes de eu chegar ao texto.

Eu também tentei converter no DatePicker TextBox.LostFocus assim:

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; 
        }
    }
}

Todas as idéias?

Foi útil?

Solução

Se você usar ligação aos dados de vinculação para o seu DatePicker, você poderia usar um ValueConverter.

Exemplo rápido de conversor de data:

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;
    }
}

controle DatePickerTextBox em XAML:

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

DatePickerTextBox em 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; }
}

Acabei de fazer uma classe chamada MyData para usar como dados desta amostra.

Outras dicas

Eu acho que você pode precisar para começar realmente vai fonte e controle total personalizar isso. O problema é que o texto é atualizado no evento TextChanged:

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

Então, pelo tempo que você chegar ao seu código perdeu o foco, o valor já foi definido. Eu era capaz de contornar este problema utilizando subclasses, mas desde TextChanged lida com cada mudança que eu não estou certo que seu método de análise irá funcionar (Uma vez que, logo que você bater um número ele vai ficar alterado para uma data).

public class CustomDatePicker : DatePicker
{
    private TextBox textBox; 

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

        if (textBox != null)
            textBox.TextChanged += 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();                 
        }  
    }
}

Ele funciona para mim desde que nada muda até que soletra a palavra inteira, mas no seu caso, que provavelmente não vai funcionar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top