Chcę zmienić format daty wybrany w DateTimePicker w WPF ApplicationJak zmienić format (np dd/MMM/rrrr) od DateTimePicker w aplikacji WPF
Odpowiedz
Zazwyczaj format czasu data jest zapisana w pliku zasobów, ponieważ pomogłoby to w internacjonalizacji aplikacji.
można odebrać format z pliku zasobów i użyć ToString(DATE_FORMAT)
W twoim przypadku może chcesz używać
dateTimePicker.SelectedDate.ToString("dd-MMM-yyyy");
w XAML:
<toolkit:DatePicker SelectedDateFormat="Long" />
lub
<toolkit:DatePicker SelectedDateFormat="Short" />
DatePicker1.SelectedDate = DatePicker1.SelectedDate.Value.ToString("dd/MM/yyyy")
Czy to się kompiluje? – code4life
Thread.CurrentThread.CurrentCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
to się zmienia w kontroli interfejsu użytkownika, ale nie w właściwości viewmodel. otrzymuję ten sam format formatu daty komputera. jakikolwiek pomysł, proszę? –
Zajmowałem się tym problemem nieludzko. Znalazłem prosty sposób na wykonanie tego niestandardowego formatu i mam nadzieję, że ci to pomoże. Pierwszą rzeczą, którą musisz zrobić, to zastosować specyficzny styl do bieżącego DatePicker podobnie jak ten, w 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>
Jak można zauważyć w tej części, istnieje konwerter nazwie DateTimeFormatter w momencie podejmowania wiążących do właściwości Text w "PART_TextBox". Ten konwerter odbiera parametr konwertera zawierający niestandardowy format. Na koniec dodajemy kod w języku C# do konwertera 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;
}
}
}
Mam nadzieję, że ci to pomoże. Daj mi znać w przypadku jakichkolwiek problemów lub sugestii poprawy.
Jeśli chodzi o mnie, zmiana środowiska na zmianę formatu DatePicker
(np. Thread.CurrentCulture
) nie jest dobrym pomysłem. Oczywiście, można utworzyć Control
pochodzący z DatePicker
i zaimplementować właściwość zależności, taką jak Format
, ale kosztuje to zbyt wiele wysiłku.
Proste i eleganckie rozwiązanie, które znalazłem, jest wartością wiążącą nie dla samej SelectedDate
, ale dla jakiejś nieużywanej właściwości (użyłem do tego atrybutu ToolTip
) i zaktualizować tę właściwość po zmianie ustawienia SelectedDate.
C realizacja # dla jednokierunkowych wiążących wygląda następująco:
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# powinien wyglądać następująco:
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;
}
Na dwukierunkowe i uchwyt dojścia ToolTipChanged
wydarzenie w ten sam sposób, aby zaktualizować SelectedDate
.
Dzięki @Fernando García za podstawę tego.
Napisałem właściwość DateFormat dołączoną do DatePicker, która umożliwia wprowadzenie ciągu formatów do wyświetlania i wprowadzania.
W przypadku danych wejściowych spróbuje przeanalizować dane za pomocą dostarczonego formatu, a następnie spróbuje przeanalizować go w bieżącym formacie kultury.
Przykład użycia z formatem pytaniem jest:
<DatePicker my:DatePickerDateFormat.DateFormat="dd/MMM/yyyy"/>
DateFormat dołączone właściwości:
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;
}
}
}
Próbowałem użyć wyżej wymienionej klasy, aby uzyskać prawidłowy format daty. Na pierwszy rzut oka myślałem, że działa zgodnie z oczekiwaniami. Ale po kilku chwilach odkryłem, że kiedy wybieram datę, otrzymuję tę datę we właściwym formacie. Dla np. Dd/mm/rrrr. Następnie, gdy przestawiłem fokus na inne sterowanie, obserwowałem, że ta data jest ponownie konwertowana do formatu domyślnego, tj. MM.dd.rrrr. Z tego obserwowałem, że DateSeparator pozostaje określony, ale format daty zmienia się, gdy tylko DatePicker traci fokus. – Vishal
Dodaj ten styl do XAML lub App.xaml złożyć
<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 To
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DateLabel.Content = Convert.ToDateTime(datePicker1.Text).ToString("dd-MM-yyyy");
}
+1 Zastanawiam się, czy istnieje sposób na dostarczenie łańcucha formatu datetime custome w XAML. –
Ta właściwość nie jest dostępna dla formantu DatePickerTextBox w oryginalnym pytaniu. – Wouter