博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF DatePicker只显示年和月 修改:可以只显示年
阅读量:5144 次
发布时间:2019-06-13

本文共 10541 字,大约阅读时间需要 35 分钟。

最近的项目,查询时只需要年和月,不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是

原文是用了两个类,其中一个是为了让DatePicker下的Calendar只显示年月,不显示日,另一个类是为了让DatePicker格式化为yyyy-MM格式,但是从文章中可以看出,有人提出了,用格式化类进行格式化时,DatePicker控件会闪动一下,当然不影响使用。如果不想使用文章中提到的类进行格式化,也可以用我上一篇文章中的方法进行格式化,不会出现闪动的情况。

只显示年月的类(2016-12-20修改,可以只显示年)

public class DatePickerCalendar    {        public static bool GetIsYear(DependencyObject obj)        {            return (bool)obj.GetValue(IsYearProperty);        }        public static void SetIsYear(DependencyObject obj, bool value)        {            obj.SetValue(IsYearProperty, value);        }        // Using a DependencyProperty as the backing store for IsYear.  This enables animation, styling, binding, etc...        public static readonly DependencyProperty IsYearProperty =            DependencyProperty.RegisterAttached("IsYear", typeof(bool), typeof(DatePickerCalendar), new PropertyMetadata(false, new PropertyChangedCallback(OnIsMonthYearChanged)));        public static readonly DependencyProperty IsMonthYearProperty =        DependencyProperty.RegisterAttached("IsMonthYear", typeof(bool), typeof(DatePickerCalendar),                                            new PropertyMetadata(OnIsMonthYearChanged));        public static bool GetIsMonthYear(DependencyObject dobj)        {            return (bool)dobj.GetValue(IsMonthYearProperty);        }        public static void SetIsMonthYear(DependencyObject dobj, bool value)        {            dobj.SetValue(IsMonthYearProperty, value);        }        private static void OnIsMonthYearChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)        {            var datePicker = (DatePicker)dobj;            Application.Current.Dispatcher                .BeginInvoke(DispatcherPriority.Loaded,                             new Action
(SetCalendarEventHandlers), datePicker, e); } private static void SetCalendarEventHandlers(DatePicker datePicker, DependencyPropertyChangedEventArgs e) { if (e.NewValue == e.OldValue) return; if ((bool)e.NewValue) { datePicker.CalendarOpened += DatePickerOnCalendarOpened; datePicker.CalendarClosed += DatePickerOnCalendarClosed; } else { datePicker.CalendarOpened -= DatePickerOnCalendarOpened; datePicker.CalendarClosed -= DatePickerOnCalendarClosed; } } private static void DatePickerOnCalendarOpened(object sender, RoutedEventArgs routedEventArgs) { var calendar = GetDatePickerCalendar(sender); if (GetIsYear(sender as DatePicker)) { calendar.DisplayMode = CalendarMode.Decade; } else { calendar.DisplayMode = CalendarMode.Year; } calendar.DisplayModeChanged += CalendarOnDisplayModeChanged; } private static void DatePickerOnCalendarClosed(object sender, RoutedEventArgs routedEventArgs) { var datePicker = (DatePicker)sender; var calendar = GetDatePickerCalendar(sender); datePicker.SelectedDate = calendar.SelectedDate; calendar.DisplayModeChanged -= CalendarOnDisplayModeChanged; } private static void CalendarOnDisplayModeChanged(object sender, CalendarModeChangedEventArgs e) { var calendar = (Calendar)sender; var datePicker = GetCalendarsDatePicker(calendar); bool mode = (GetIsYear(datePicker) && calendar.DisplayMode != CalendarMode.Year) || (GetIsMonthYear(datePicker) && calendar.DisplayMode != CalendarMode.Month); if (mode) return; calendar.SelectedDate = GetSelectedCalendarDate(calendar.DisplayDate); datePicker.IsDropDownOpen = false; } private static Calendar GetDatePickerCalendar(object sender) { var datePicker = (DatePicker)sender; var popup = (Popup)datePicker.Template.FindName("PART_Popup", datePicker); return ((Calendar)popup.Child); } private static DatePicker GetCalendarsDatePicker(FrameworkElement child) { var parent = (FrameworkElement)child.Parent; if (parent.Name == "PART_Root") return (DatePicker)parent.TemplatedParent; return GetCalendarsDatePicker(parent); } private static DateTime? GetSelectedCalendarDate(DateTime? selectedDate) { if (!selectedDate.HasValue) return null; return new DateTime(selectedDate.Value.Year, selectedDate.Value.Month, 1); } }
DatePickerCalendar

调用方式

展示效果

从图上就能看到左右不一样,左侧的是添加附加属性的,点击以后直接显示月,后侧没用的则显示到日,虽然都格式化为了yyyy-MM,但是Calendar如果显示到日的话,用户体验不好。

========================================================================================================================

2015年8月4日 记:

今天在项目中发现一个问题,就是采用我上一篇帖子中的三句话进行DatePicker时间的格式化显示,但是由于用的是Thread,所以是在线程里进行格式化的,因此,影响到了同事做的其他模块,因为大部分都是格式化为yyyy-MM-dd,但是由于我的一个页面是格式化为了yyyy-MM,而其中的一个同事并没有在他的构造函数里使用三句格式化他的DatePicker,从而导致他其他的时间计算出现问题,因此在保证原有功能不变的情况下,需要显示yyyy-MM,就需要用到原帖子中的另一个类。

DatePickerDateFormat

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
(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, 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
)parameter).Item2; var selectedDate = (DateTime?)value; return DateTimeToString(formatStr, selectedDate); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var tupleParam = ((Tuple
)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

总的调用方法 

 ========================================================================================================================

2016年12月20日

修改原来的代码,增加IsYear附加属性,用法和IsMonthYear一样,设置为True则只显示年份

转载于:https://www.cnblogs.com/ZXdeveloper/p/4665772.html

你可能感兴趣的文章
第4次作业-案例分析
查看>>
[转载]AMOLED结构详解,BOE专家给你分析驱动补偿
查看>>
动态调用web服务
查看>>
English trip -- VC(情景课)2 A At school
查看>>
English trip M1 - PC1 Are you a Model? 你是模特吗? Teacher:Taylor
查看>>
【MySQL运维实践】
查看>>
Wireshark抓取iPhone的数据包
查看>>
●BZOJ 2007 NOI 2010 海拔
查看>>
●BZOJ 4516 [Sdoi2016]生成魔咒
查看>>
H3C交换机配置命令(收集)
查看>>
HDFS简介
查看>>
【Python】重定向 Stream 到文件
查看>>
centos云服务器安装svn
查看>>
Lucene4:获取中文分词结果,根据文本计算boost
查看>>
linux服务器如何添加sudo用户
查看>>
栈(链式存储结构)
查看>>
Houdini中角色通用修穿插方法
查看>>
【Python】Python中*args 和**kwargs的用法
查看>>
自定义带下划线文本的UIButton
查看>>
校园跳蚤市场-Sprint计划(第二阶段)
查看>>