WPF 可选择年月及显示格式的DatePicker控件
2016-09-13 17:05
465 查看
转载于 http://www.cnblogs.com/ZXdeveloper/archive/2015/07/21/4665772.html
代码部分:
样式部分:
代码部分:
public class XDatePicker : DatePicker { static XDatePicker() { DefaultStyleKeyProperty.OverrideMetadata(typeof(XDatePicker), new FrameworkPropertyMetadata(typeof(XDatePicker))); } #region 属性 static bool IsMonthYear, IsYear; #region IsMonthYear public static bool GetIsMonthYear(DependencyObject dobj) { return (bool)dobj.GetValue(IsMonthYearProperty); } public static void SetIsMonthYear(DependencyObject dobj, bool value) { dobj.SetValue(IsMonthYearProperty, value); } public static readonly DependencyProperty IsMonthYearProperty = DependencyProperty.RegisterAttached("IsMonthYear", typeof(bool), typeof(XDatePicker), new PropertyMetadata(OnIsMonthYearChanged)); private static void OnIsMonthYearChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e) { var datePicker = (XDatePicker)dobj; IsMonthYear = GetIsMonthYear(dobj); Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action<XDatePicker, DependencyPropertyChangedEventArgs>(SetCalendarEventHandlers), datePicker, e); } #endregion #region IsYear public static bool GetIsYear(DependencyObject dobj) { return (bool)dobj.GetValue(IsYearProperty); } public static void SetIsYear(DependencyObject dobj, bool value) { dobj.SetValue(IsYearProperty, value); } public static readonly DependencyProperty IsYearProperty = DependencyProperty.RegisterAttached("IsYear", typeof(bool), typeof(XDatePicker), new PropertyMetadata(OnIsYearChanged)); private static void OnIsYearChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e) { var datePicker = (XDatePicker)dobj; IsYear = GetIsYear(dobj); Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action<XDatePicker, DependencyPropertyChangedEventArgs>(SetCalendarEventHandlers), datePicker, e); } #endregion #region DateFormat public static string GetDateFormat(DependencyObject dobj) { return (string)dobj.GetValue(DateFormatProperty); } public static void SetDateFormat(DependencyObject dobj, string value) { dobj.SetValue(DateFormatProperty, value); } public static readonly DependencyProperty DateFormatProperty = DependencyProperty.RegisterAttached("DateFormat", typeof(string), typeof(XDatePicker), new PropertyMetadata(OnDateFormatChanged)); private static void OnDateFormatChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e) { var datePicker = (XDatePicker)dobj; Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action<XDatePicker>(ApplyDateFormat), datePicker); } private static void ApplyDateFormat(XDatePicker datePicker) { var binding = new Binding("SelectedDate") { RelativeSource = new RelativeSource { AncestorType = typeof(XDatePicker) }, Converter = new DatePickerDateTimeConverter(), ConverterParameter = new Tuple<XDatePicker, 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; e.Handled = true; var textBox = (TextBox)sender; var datePicker = (XDatePicker)textBox.TemplatedParent; var dateStr = textBox.Text; var formatStr = GetDateFormat(datePicker); datePicker.SelectedDate = DatePickerDateTimeConverter.StringToDateTime(datePicker, formatStr, dateStr); } private class DatePickerDateTimeConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var formatStr = ((Tuple<XDatePicker, 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<XDatePicker, 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(XDatePicker 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; } } #endregion private static void SetCalendarEventHandlers(XDatePicker 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 (IsMonthYear) calendar.DisplayMode = CalendarMode.Year; if (IsYear) calendar.DisplayMode = CalendarMode.Decade; var datePicker = (XDatePicker)sender; var textBox = GetTemplateTextBox(datePicker); var formatStr = GetDateFormat(datePicker); textBox.Text = DatePickerDateTimeConverter.DateTimeToString(formatStr, datePicker.SelectedDate); calendar.DisplayModeChanged += CalendarOnDisplayModeChanged; } private static void DatePickerOnCalendarClosed(object sender, RoutedEventArgs routedEventArgs) { var datePicker = (XDatePicker)sender; var calendar = GetDatePickerCalendar(sender); datePicker.SelectedDate = calendar.SelectedDate; calendar.DisplayModeChanged -= CalendarOnDisplayModeChanged; } private static void CalendarOnDisplayModeChanged(object sender, CalendarModeChangedEventArgs e) { var calendar = (System.Windows.Controls.Calendar)sender; if (IsMonthYear && calendar.DisplayMode != CalendarMode.Month) return; if (IsYear && calendar.DisplayMode != CalendarMode.Year) return; calendar.SelectedDate = GetSelectedCalendarDate(calendar.DisplayDate); var datePicker = GetCalendarsDatePicker(calendar); datePicker.IsDropDownOpen = false; } private static System.Windows.Controls.Calendar GetDatePickerCalendar(object sender) { var datePicker = (XDatePicker)sender; var popup = (Popup)datePicker.Template.FindName("PART_Popup", datePicker); return ((System.Windows.Controls.Calendar)popup.Child); } private static XDatePicker GetCalendarsDatePicker(FrameworkElement child) { var parent = (FrameworkElement)child.Parent; if (parent.Name == "PART_Root") return (XDatePicker)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); } #endregion }
样式部分:
<Style TargetType="{x:Type local:XDatePicker}"> <Setter Property="Height" Value="28"/> <Setter Property="Width" Value="100"/> <Setter Property="Margin" Value="5,0"/> <Setter Property="BorderBrush" Value="gray"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="SelectedDateFormat" Value="Short"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:XDatePicker}"> <Border CornerRadius="3" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="Disabled"> <Storyboard> <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Popup"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <DockPanel x:Name="PART_Root"> <DockPanel.Resources> <ControlTemplate x:Key="DropDownButtonTemplate" TargetType="{x:Type Button}"> <Border Height="18" Width="18"> <Path x:Name="calendar" Fill="#FF368DC0" RenderTransformOrigin="0.5,0.5" Stretch="Fill" <span style="white-space:pre"> </span> Data="F1 M 18.0025,57.0081L 18.0025,23.0032L 23.0032,23.0032L 23.0032,20.0028C 23.0033,18.898 23.8988,18.0025 25.0035,18.0025L 29.004,18.0025C 30.1087,18.0025 31.0042,18.898 31.0043,20.0026L 31.0043,23.0032L 45.0063,23.0032L 45.0062,20.0026C 45.0062,18.8978 45.9018,18.0023 47.0065,18.0023L 51.0071,18.0023C 52.1118,18.0023 53.0074,18.8978 53.0074,20.0026L 53.0074,23.0032L 58.0081,23.0032L 58.0081,57.0081L 18.0025,57.0081 Z M 20,54L 56,54L 56,28L 20,28L 20,54 Z M 23,44L 31,44L 31,52L 23,52L 23,44 Z M 34,44L 42,44L 42,52L 34,52L 34,44 Z M 45,44L 53,44L 53,52L 45,52L 45,44 Z M 23,32L 31,32L 31,40L 23,40L 23,32 Z M 34,32L 42,32L 42,40L 34,40L 34,32 Z M 45,32L 53,32L 53,40L 45,40L 45,32 Z M 48.5067,20.0029C 47.6782,20.0029 47.0065,20.6745 47.0065,21.5031L 47.0065,24.5035C 47.0065,25.332 47.6782,26.0037 48.5067,26.0037L 49.5068,26.0037C 50.3354,26.0037 51.0071,25.332 51.0071,24.5035L 51.0071,21.5031C 51.0071,20.6745 50.3354,20.0029 49.5068,20.0029L 48.5067,20.0029 Z M 26.5037,20.0028C 25.6751,20.0028 25.0035,20.6745 25.0035,21.503L 25.0035,24.5035C 25.0035,25.332 25.6751,26.0037 26.5037,26.0037L 27.5038,26.0037C 28.3324,26.0037 29.004,25.332 29.004,24.5035L 29.004,21.503C 29.004,20.6745 28.3324,20.0028 27.5038,20.0028L 26.5037,20.0028 Z "/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="calendar" Property="Fill" Value="#1BBBFA"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </DockPanel.Resources> <Button x:Name="PART_Button" DockPanel.Dock="Right" Foreground="{TemplateBinding Foreground}" Focusable="False" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="3,0" Template="{StaticResource DropDownButtonTemplate}" Width="20"/> <Grid Margin="3,0,0,0"> <DatePickerTextBox x:Name="PART_TextBox" Focusable="{TemplateBinding Focusable}" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Center"/> <Popup x:Name="PART_Popup" IsHitTestVisible="False" Opacity="0" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_TextBox}" StaysOpen="False"/> </Grid> </DockPanel> </Border> <ControlTemplate.Triggers> <DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="false"> <Setter Property="Foreground" TargetName="PART_TextBox" Value="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"/> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
相关文章推荐
- Android日历选择控件DatePickerDialog只显示年月
- WPF DatePicker日期控件只显示年月
- 日期控件NoDayDatePicker只显示年月不显示日 兼容5.0以上的方法
- Kendo Ui 中日期控件DatePicker显示格式更改
- Kendo Ui 中日期控件DatePicker显示格式更改
- EasyUi日期控件datebox设置,只显示年月,也只能选择年月
- 日期控件DatePicker只显示年月不显示日
- WPF -- 设置 DatePicker 的日期时间显示格式
- [code]使Ext.DatePicker只显示年月选择界面
- 日期控件DatePicker只显示年月不显示日
- WPF控件DatePicker默认显示当前时间
- Ext DateField 控件的日期选择控件DatePicker 布局 显示异常问题
- extjs实现年月格式的日期选择(DatePicker)
- DatePicker控件/日期控件,只显示年月/隐藏日
- Date Time Picker时间控件只能显示日期或时分秒,我怎么才能让它在界面上同时显示出两者,并且保证点击下拉按钮时可编辑日期? 2010-11-24 19:47
- jQuery里面的datepicker日期控件默认是显示英文的,如何显示中文或其他语言呢?
- Windows Phone 7 日期选择控件DatePicker和时间选择控件TimePicker
- Asp.net2.0 DatePicker控件 ,日期选择控件 ,Javascript
- WPF 4 日期选择器(DatePicker)
- WPF控件之DataGrid, DatePicker, Grid, GridSplitter, HyperlinkButton, Image