最近的项目,查询时只需要年和月,不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是http://stackoverflow.com/questions/1798513/wpf-toolkit-datepicker-month-year-only

原文是用了两个类,其中一个是为了让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<DatePicker, DependencyPropertyChangedEventArgs>(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, );
}
}

DatePickerCalendar

调用方式

<DatePicker Width="" Height="" local:DatePickerCalendar.IsMonthYear="True"/>

展示效果

从图上就能看到左右不一样,左侧的是添加附加属性的,点击以后直接显示月,后侧没用的则显示到日,虽然都格式化为了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<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

总的调用方法

<DatePicker conver:DatePickerCalendar.IsMonthYear="True" conver:DatePickerDateFormat.DateFormat="yyyy-MM" />

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

2016年12月20日

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

WPF DatePicker只显示年和月 修改:可以只显示年的更多相关文章

  1. jquery datepicker只显示年和月

    <html xmlns="http://www.w3.org/1999/xhtml"> <head >     <title></titl ...

  2. WPF DatePicker默认显示当前日期,格式化为年月日

    原文:WPF DatePicker默认显示当前日期 WPF的日历选择控件默认为当前日期,共有两种方法,一种静态,一种动态. 静态的当然写在DatePicker控件的属性里了,动态的写在对应的cs文件里 ...

  3. EF 外键不显示、如何让外键显示!增、删、改 操作时,外键不显示,只显示导航属性!

    一.问题描述:EF 外键不显示.如何让外键显示!增.删.改 操作时,外键不显示,只显示导航属性! EF 添加.增加.插入数据时,外键不显示! 二.解决方案:在根据数据库生成模型的时候,选中“在模型中” ...

  4. 【节点-添加标签】【节点-删除标签】【显示年-月-日-星期】【math算数】【正则表达式】

    1.节点-添加标签 <body><div id="div1"><p id="p1">这是一个段落.</p>< ...

  5. fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤)(转)

    fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤) Fiddler 有一个filters可以很好的帮助我们只显示我们关系的请求或 ...

  6. 好玩的WPF第一弹:窗口抖动+边框阴影效果+倒计时显示文字

    原文:好玩的WPF第一弹:窗口抖动+边框阴影效果+倒计时显示文字 版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csd ...

  7. ListView 分页显示(转载+修改)上

    实习工作中,分配到了一个给已经上线的android成品增加需求的任务,其中一项是给每个信息显示增加分页显示的功能(ListView的显示),于是上网查资料,看到了: 原地址:http://www.cn ...

  8. CODESOFT对话框中的显示字体怎么修改

      不同的人其使用软件的视觉习惯是不一样的,直接给大家介绍过如何设置CODESOFT的界面语言,这是一个大范围的界面显示设置.本文,将介绍如何修改CODESOFT对话框显示的字体,以满足自己的视觉习惯 ...

  9. WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )

    WPF:谈谈各种多线程去修改或访问UI线程数据的方法http://www.cnblogs.com/mgen/archive/2012/03/10/2389509.html 子线程非法访问UI线程的数据 ...

随机推荐

  1. 关于使用iframe嵌套页面的跳转方式

    一.背景A,B,C,D都是jsp,D是C的iframe,C是B的iframe,B是A的iframe,在D中跳转页面的写法区别如下. 二.JS跳转window.location.href.locatio ...

  2. ASCII字符集中的功能/控制字符

       ASCII字符集中的功能/控制字符     Function/Control Code/Character in ASCII Version: 2011-02-15 Author: gree ...

  3. 学用了QT觉得QT较怪异

    如果让我选择不会用qt 还是用界面开源库,boost.

  4. (转)windows系统下Python环境的搭建

    原博文地址:http://www.cnblogs.com/windinsky/archive/2012/09/20/2695520.html 这段时间在做python,觉得这个配置环境的帖子还不错,分 ...

  5. sql编程篇 (五) 事务

    计算机中的事务 编辑 概念 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用 ...

  6. 最近在新公司的一些HTML学习

    还是先把代码贴在这  后期再写感想 <!DOCTYPE html> <head> <meta http-equiv="x-ua-compatible" ...

  7. http长轮询&短轮询

    http 协议介绍: http 协议是请求/响应范式的, 每一个 http 响应都是由一个对应的 http 请求产生的; http 协议是无状态的, 多个 http 请求之间是没有关系的. http ...

  8. HTML 常用标签

    一.基础标签 <!-- -->    定义注释 <!DOCTYPE> 定义文档类型 <style> 定义文档的样式信息 <meta> 定义关于HTML文 ...

  9. [转]runtime 消息机制

    原文地址:http://www.jianshu.com/p/f6300eb3ec3d 一.关于runtime 之前在项目中有遇到过用runtime解决改变全局字体的问题,所以再一次感受到了runtim ...

  10. SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输

    SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输 微软高兴地宣布所有主流SQL Server客户端驱动和SQL Server发行版已经支持T ...