voglio cambiare il formato di data selezionata in DateTimePicker in WPF ApplicationCome cambiare formato (ad esempio gg/MMM/aaaa) di DateTimePicker in applicazione WPF
risposta
In genere il formato di data e ora viene memorizzato in un file di risorse, perché ciò contribuirebbe all'internazionalizzazione dell'app.
È possibile ritirare il formato dal file di risorse e utilizzare un ToString(DATE_FORMAT)
Nel tuo caso si potrebbe desiderare di utilizzare
dateTimePicker.SelectedDate.ToString("dd-MMM-yyyy");
In XAML:
<toolkit:DatePicker SelectedDateFormat="Long" />
o
<toolkit:DatePicker SelectedDateFormat="Short" />
DatePicker1.SelectedDate = DatePicker1.SelectedDate.Value.ToString("dd/MM/yyyy")
Compilano anche questo? – code4life
Thread.CurrentThread.CurrentCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
questo sta cambiando nel controllo dell'interfaccia utente ma non nella proprietà viewmodel. Sto ottenendo lo stesso formato del formato della data del computer. qualche idea per favore? –
Mi stavo occupando di questo problema rencetly. Ho trovato un modo semplice per eseguire questo formato personalizzato e spero che questo ti aiuti. La prima cosa che devi fare è applicare uno stile specifico per il DatePicker corrente proprio come questo, in XAML:
<DatePicker.Resources>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox" Width="113" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Text="{Binding Path=SelectedDate,Converter={StaticResource DateTimeFormatter},RelativeSource={RelativeSource AncestorType={x:Type DatePicker}},ConverterParameter=dd-MMM-yyyy}" BorderBrush="{DynamicResource BaseBorderBrush}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
Come si può notare in questa parte, esiste un convertitore chiamato DateTimeFormatter al momento di rendere vincolante alla proprietà Text di "PART_TextBox". Questo convertitore riceve il parametro di conversione che include il formato personalizzato. Infine aggiungiamo il codice in C# per il convertitore DateTimeFormatter.
public class DateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DateTime? selectedDate = value as DateTime?;
if (selectedDate != null)
{
string dateTimeFormat = parameter as string;
return selectedDate.Value.ToString(dateTimeFormat);
}
return "Select Date";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
var valor = value as string;
if (!string.IsNullOrEmpty(valor))
{
var retorno = DateTime.Parse(valor);
return retorno;
}
return null;
}
catch
{
return DependencyProperty.UnsetValue;
}
}
}
Spero che questo aiuto a voi. Per favore fatemi sapere per qualsiasi problema o suggerendo di migliorare.
Per quanto mi riguarda, cambiare l'ambiente per modificare il formato DatePicker
(come Thread.CurrentCulture
) non è una buona idea. Certo, è possibile creare derivato da DatePicker
e implementare la proprietà di dipendenza come Format
, ma ciò comporta uno sforzo eccessivo.
soluzione semplice ed elegante che ho trovato è il valore vincolante non SelectedDate
per sé, ma per qualche proprietà non utilizzata (io ho usato ToolTip
proprietà per questo) e aggiornare questa proprietà quando SelectedDate viene modificata.
C implementazione # per senso unico aspetto vincolanti come questo:
DatePicker datePicker = new DatePicker();
datePicker.SetBinding(ToolTipProperty, "Date");
datePicker.SelectedDateChanged += (s, ea) =>
{
DateTime? date = datePicker.SelectedDate;
string value = date != null ? date.Value.ToString("yyyy-MM-dd") : null;
datePicker.ToolTip = value;
};
XAML + C# dovrebbe apparire così:
XAML:
<DatePicker ToolTip="{Binding Date Mode=TwoWay}"
SelectedDateChanged="DatePicker_SelectedDateChanged"/>
C#:
private void DatePicker_SelectedDateChanged(object sender, EventArgs ea)
{
DatePicker datePicker = (DatePicker)sender;
DateTime? date = datePicker.SelectedDate;
string value = date != null ? date.Value.ToString("yyyy-MM-dd") : null;
datePicker.ToolTip = value;
}
Per due vie i mplementation handle ToolTipChanged
evento allo stesso modo per aggiornare SelectedDate
.
Grazie a @Fernando García per la base di questo.
Ho scritto una proprietà DateFormat per DatePicker che consente di fornire una stringa di formato per la visualizzazione e l'immissione.
Per l'input tenterà di analizzare utilizzando il formato fornito, ricadendo nel tentativo di analizzarlo con il formato della cultura corrente.
Esempio di utilizzo con il formato della domanda:
<DatePicker my:DatePickerDateFormat.DateFormat="dd/MMM/yyyy"/>
La proprietà DateFormat allegato è:
public class DatePickerDateFormat
{
public static readonly DependencyProperty DateFormatProperty =
DependencyProperty.RegisterAttached("DateFormat", typeof (string), typeof (DatePickerDateFormat),
new PropertyMetadata(OnDateFormatChanged));
public static string GetDateFormat(DependencyObject dobj)
{
return (string) dobj.GetValue(DateFormatProperty);
}
public static void SetDateFormat(DependencyObject dobj, string value)
{
dobj.SetValue(DateFormatProperty, value);
}
private static void OnDateFormatChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
{
var datePicker = (DatePicker) dobj;
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Loaded, new Action<DatePicker>(ApplyDateFormat), datePicker);
}
private static void ApplyDateFormat(DatePicker datePicker)
{
var binding = new Binding("SelectedDate")
{
RelativeSource = new RelativeSource {AncestorType = typeof (DatePicker)},
Converter = new DatePickerDateTimeConverter(),
ConverterParameter = new Tuple<DatePicker, string>(datePicker, GetDateFormat(datePicker))
};
var textBox = GetTemplateTextBox(datePicker);
textBox.SetBinding(TextBox.TextProperty, binding);
textBox.PreviewKeyDown -= TextBoxOnPreviewKeyDown;
textBox.PreviewKeyDown += TextBoxOnPreviewKeyDown;
datePicker.CalendarOpened -= DatePickerOnCalendarOpened;
datePicker.CalendarOpened += DatePickerOnCalendarOpened;
}
private static TextBox GetTemplateTextBox(Control control)
{
control.ApplyTemplate();
return (TextBox) control.Template.FindName("PART_TextBox", control);
}
private static void TextBoxOnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Return)
return;
/* DatePicker subscribes to its TextBox's KeyDown event to set its SelectedDate if Key.Return was
* pressed. When this happens its text will be the result of its internal date parsing until it
* loses focus or another date is selected. A workaround is to stop the KeyDown event bubbling up
* and handling setting the DatePicker.SelectedDate. */
e.Handled = true;
var textBox = (TextBox) sender;
var datePicker = (DatePicker) textBox.TemplatedParent;
var dateStr = textBox.Text;
var formatStr = GetDateFormat(datePicker);
datePicker.SelectedDate = DatePickerDateTimeConverter.StringToDateTime(datePicker, formatStr, dateStr);
}
private static void DatePickerOnCalendarOpened(object sender, RoutedEventArgs e)
{
/* When DatePicker's TextBox is not focused and its Calendar is opened by clicking its calendar button
* its text will be the result of its internal date parsing until its TextBox is focused and another
* date is selected. A workaround is to set this string when it is opened. */
var datePicker = (DatePicker) sender;
var textBox = GetTemplateTextBox(datePicker);
var formatStr = GetDateFormat(datePicker);
textBox.Text = DatePickerDateTimeConverter.DateTimeToString(formatStr, datePicker.SelectedDate);
}
private class DatePickerDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var formatStr = ((Tuple<DatePicker, string>) parameter).Item2;
var selectedDate = (DateTime?) value;
return DateTimeToString(formatStr, selectedDate);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var tupleParam = ((Tuple<DatePicker, string>) parameter);
var dateStr = (string) value;
return StringToDateTime(tupleParam.Item1, tupleParam.Item2, dateStr);
}
public static string DateTimeToString(string formatStr, DateTime? selectedDate)
{
return selectedDate.HasValue ? selectedDate.Value.ToString(formatStr) : null;
}
public static DateTime? StringToDateTime(DatePicker datePicker, string formatStr, string dateStr)
{
DateTime date;
var canParse = DateTime.TryParseExact(dateStr, formatStr, CultureInfo.CurrentCulture,
DateTimeStyles.None, out date);
if (!canParse)
canParse = DateTime.TryParse(dateStr, CultureInfo.CurrentCulture, DateTimeStyles.None, out date);
return canParse ? date : datePicker.SelectedDate;
}
}
}
Ho provato a utilizzare la classe sopra indicata per ottenere il formato di data corretto. A prima vista pensavo che funzionasse come previsto. Ma dopo alcuni momenti ho scoperto che quando seleziono una data ottengo quella data nel formato corretto. Ad es. gg.mm.aaaa. Poi, quando ho spostato l'attenzione su altri controlli, ho visto che la data è stata nuovamente convertita nel formato predefinito, ad esempio MM.dd.yyyy. Da questo ho osservato che rimane il DateSeparator che viene specificato, ma il formato della data cambia non appena DatePicker perde il focus. – Vishal
Aggiungi questo stile al vostro XAML o App.xaml il file
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox"
Text="{Binding Path=SelectedDate, StringFormat='dd.MM.yyyy',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Try Questo
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DateLabel.Content = Convert.ToDateTime(datePicker1.Text).ToString("dd-MM-yyyy");
}
+1 Mi chiedo se esiste un modo per fornire una stringa di formato data/ora custame in XAML. –
Questa proprietà non è disponibile per il controllo DatePickerTextBox nella domanda originale. – Wouter