Domanda

Voglio DatePicker per convertire le seguenti parti di testo in DateTime (mostrato in formato internazionale) in modo che i miei clienti possano scrivere una data in DatePicker casella di testo più veloce, quindi non è solo DateTime.Parse che userò:

"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

Ho provato diversi metodi per farlo ma non funzionano. Ho provato a associare DatePicker.Text / DatePicker.SelectedDate / DatePicker.DisplayDate con un convertitore di valori personalizzato. Ma non funziona perché DatePicker ha già elaborato il testo prima di arrivare al testo.

Ho anche provato a convertire in DatePicker TextBox.LostFocus in questo modo:

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

Qualche idea?

È stato utile?

Soluzione

Se si utilizza Binding per associare i dati a DatePicker, è possibile utilizzare ValueConverter.

Esempio rapido di convertitore di date:

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

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

Ho appena creato una classe chiamata MyData da utilizzare come dati in questo esempio.

Altri suggerimenti

Penso che potresti dover effettivamente avviare la fonte di controllo completo e personalizzarla. Il problema è che il testo viene aggiornato nell'evento TextChanged:

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

Quindi, quando arrivi al tuo codice focus perso, il valore è già stato impostato. Sono stato in grado di aggirare questo problema utilizzando la sottoclasse, ma poiché TextChanged gestisce ogni modifica, non sono sicuro che il tuo metodo di analisi funzionerà (poiché non appena premi 1 numero verrà cambiato in una 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();                 
        }  
    }
}

Funziona per me dal momento che nulla cambia fino a quando non scrive la parola intera, ma nel tuo caso probabilmente non funzionerà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top