.net 如何在WPF应用程序中更改DateTimePicker的格式(如dd/MMM/yyyy)

.net 如何在WPF应用程序中更改DateTimePicker的格式(如dd/MMM/yyyy),.net,wpf,datetime,datetimepicker,datetime-format,.net,Wpf,Datetime,Datetimepicker,Datetime Format,我想更改在WPF应用程序的DateTimePicker中选择的日期格式。通常,日期时间格式存储在资源文件中,因为这将有助于应用程序的国际化 您可以从资源文件中选择格式并使用ToString(日期格式) 在您的情况下,您可能需要使用 dateTimePicker.SelectedDate.ToString("dd-MMM-yyyy"); 在XAML中: <toolkit:DatePicker SelectedDateFormat="Long" /> 或 我正在紧急处理这个问题。

我想更改在WPF应用程序的DateTimePicker中选择的日期格式。通常,日期时间格式存储在资源文件中,因为这将有助于应用程序的国际化

您可以从资源文件中选择格式并使用
ToString(日期格式)

在您的情况下,您可能需要使用

dateTimePicker.SelectedDate.ToString("dd-MMM-yyyy");
在XAML中:

<toolkit:DatePicker SelectedDateFormat="Long" />


我正在紧急处理这个问题。我找到了一个简单的方法来执行这种自定义格式,我希望这对您有所帮助。您需要做的第一件事是在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>

我希望这对你有帮助。请让我知道任何问题或改进建议。

对于我来说,更改环境以更改
DatePicker
格式(如
Thread.CurrentCulture
)不是一个好主意。 当然,您可以创建从
DatePicker
派生的
控件
,并实现类似
格式
的依赖项属性,但这需要花费太多的精力

我找到的简单而优雅的解决方案不是将值绑定到
SelectedDate
本身,而是绑定到一些未使用的属性(我为此使用了
ToolTip
属性),并在更改SelectedDate时更新此属性

单向绑定的C#实现如下所示:

    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#应该是这样的:

    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:


对于双向实现句柄
ToolTipChanged
事件,更新
SelectedDate

的方法与更新
SelectedDate的方法相同,感谢@Fernando García的支持

我已经为DatePicker编写了一个DateFormat附加属性,它允许您提供一个用于显示和输入的格式字符串

对于输入,它将尝试使用提供的格式进行解析,然后返回到使用当前区域性的格式进行解析

问题格式的用法示例:

<DatePicker my:DatePickerDateFormat.DateFormat="dd/MMM/yyyy"/>

DateFormat附加属性是:

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;
        }
    }
}
公共类DatePickerDateFormat
{
公共静态只读DependencyProperty DateFormatProperty=
DependencyProperty.RegisterAttached(“DateFormat”、typeof(string)、typeof(DatePickerDateFormat),
新属性元数据(OnDateFormatChanged));
公共静态字符串GetDateFormat(DependencyObject dobj)
{
返回(字符串)dobj.GetValue(DateFormatProperty);
}
公共静态void SetDateFormat(DependencyObject dobj,字符串值)
{
dobj.SetValue(DateFormatProperty,value);
}
私有静态void OnDateFormatChanged(DependencyObject dobj、DependencyPropertyChangedEventArgs e)
{
var datePicker=(datePicker)dobj;
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Loaded,新操作(ApplyDateFormat),日期选择器;
}
私有静态void ApplyDateFormat(日期选择器日期选择器)
{
变量绑定=新绑定(“SelectedDate”)
{
RelativeSource=new RelativeSource{AncestorType=typeof(日期选择器)},
Converter=新的DatePickerDateTimeConverter(),
ConverterParameter=新元组(日期选择器,GetDateFormat(日期选择器))
};
var textBox=GetTemplateTextBox(日期选择器);
textBox.SetBinding(textBox.TextProperty,binding);
textBox.PreviewKeyDown-=TextBoxOnPreviewKeyDown;
textBox.PreviewKeyDown+=TextBoxOnPreviewKeyDown;
datePicker.CalendarOpen-=DatePickerOnCalendarOpen;
datePicker.CalendarOpen+=DatePickerOnCalendarOpen;
}
私有静态文本框GetTemplateTextBox(控件)
{
control.ApplyTemplate();
return(TextBox)control.Template.FindName(“PART_TextBox”,control);
}
私有静态void TextBoxOnPreviewKeyDown(对象发送方,KeyEventArgs e)
{
if(e.Key!=Key.Return)
返回;
/*DatePicker订阅其文本框的KeyDown事件,以便在Key.Return为时设置其SelectedDate
*当这种情况发生时,其文本将是其内部日期解析的结果,直到
*失去焦点或选择了另一个日期。解决方法是停止按键事件冒泡
*和处理设置DatePicker.SelectedDate*/
e、 已处理=正确;
var textBox=(textBox)发送方;
var datePicker=(datePicker)textBox.TemplatedParent;
var dateStr=textBox.Text;
var formatStr=GetDateFormat(日期选择器);
datePicker.SelectedDate=DatePickerDateTimeConverter.StringToDateTime(datePicker,formatStr,dateStr);
}
私有静态无效日期选择器日历已打开(对象发送方,RoutedEventArgs e)
{
/*当DatePicker的文本框没有焦点且其日历通过单击其日历按钮打开时
*它的文本将是内部日期解析的结果,直到它的文本框被聚焦和另一个
*已选择日期。解决方法是在打开该字符串时设置该字符串*/
var datePicker=(datePicker)发送方;
var textBox=GetTemplateTextBox(日期选择器);
var formatStr=GetDateFormat(日期选择器);
textBox.Text=DatePickerDateTimeConverter.DateTimeToString(formatStr,datePicker.SelectedDate);
}
私有类DatePickerDateTimeConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
var formatStr=((元组)参数);
var selectedDate=(日期时间?)值;
返回日期时间字符串(formatStr,selectedDate);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
var tupleParam=((Tuple)参数);
var dateStr=(字符串)值;
返回StringToDateTime(tupleParam.Item1、tupleParam.Item2、dat
    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;
        };
<DatePicker ToolTip="{Binding Date Mode=TwoWay}"
            SelectedDateChanged="DatePicker_SelectedDateChanged"/>
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;
}
<DatePicker my:DatePickerDateFormat.DateFormat="dd/MMM/yyyy"/>
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;
        }
    }
}
 <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>
    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
      DateLabel.Content = Convert.ToDateTime(datePicker1.Text).ToString("dd-MM-yyyy");
    }