与 Winforms 中的 DateTimePicker 一样的 WPF DateTimePicker






4.63/5 (11投票s)
与 Winforms 中的 DateTimePicker 一样的 WPF DateTimePicker
引言
当我开始从 Winforms 迁移到 WPF 时,有一个控件我非常想念,那就是 Winforms 中实现的 DateTimePicker
。WPF 有 datepicker
,但我想拥有一个可以轻松地从年到月到日进行选项卡切换,并使用箭头键更改值的控件。
注意:Qwertie 已经制作了这个控件的优秀 C# 版本,并在此过程中修复了最糟糕的错误。:) 你可以在 https://gist.github.com/1150228 查看他的版本。
背景
这段代码涉及一些在 WPF 中构建用户控件时所需的基本技术。
Using the Code
要使用这段代码,只需编译 DTPicker
并在你的项目中添加对 DLL 的引用。(或者将 DTPicker
项目作为子项目包含到你的项目中。解决方案包含两个项目;DTPicker
,其中包含 usercontrol
,以及 TestDTPicker
,一个用于测试 DateTimePicker
的小型 WPF 项目。)
XAML
该控件的 XAML 相当简单明了。
<UserControl x:Class="DateTimePicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:DTPicker="clr-namespace:DTPicker">
<UserControl.Resources>
<ControlTemplate x:Key="IconButton"
TargetType="{x:Type ToggleButton}">
<Border>
<ContentPresenter />
</Border>
</ControlTemplate>
<DTPicker:BoolInverterConverter x:Key="BoolInverterConverter" />
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="DateDisplay"
VerticalContentAlignment="Center"
Margin="0,0,0,0"
MinHeight="{Binding ElementName=PopUpCalendarButton,
Path=ActualHeight}" >2001-01-01 12:30</TextBox>
<ToggleButton Template="{StaticResource IconButton}"
MaxHeight="21"
Margin="-1,0,0,0"
Name="PopUpCalendarButton"
IsChecked="False"
IsHitTestVisible="{Binding ElementName=CalendarPopup,
Path=IsOpen, Mode=OneWay, Converter={StaticResource BoolInverterConverter}}" >
<Image Source="Calendar.Icon.bmp" Stretch="
None" HorizontalAlignment="Left" />
</ToggleButton>
<Popup IsOpen="{Binding Path=IsChecked, ElementName=PopUpCalendarButton}"
x:Name="CalendarPopup" Margin="0,-7,0,0"
PopupAnimation="Fade"
StaysOpen="False">
<Calendar Margin="0,-1,0,0"
x:Name="CalDisplay" ></Calendar>
</Popup>
</StackPanel>
</UserControl>
代码
我们的控件中有四个主要变量
SelectedDate
- 选定的日期 :)DateFormat
- 日期应该如何显示 (yyyy-MM-hh 等)MinimumDate
- 可以选择的最小日期值MaximumDate
- 可以选择的最大日期值
有趣的是,SelectedDate
、MinimumDate
和 MaximumDate
的值都是相互关联的。因此,在为这些声明依赖属性时,我必须包含一个强制回调函数。
Public Shared ReadOnly SelectedDateProperty As DependencyProperty = _
DependencyProperty.Register("SelectedDate", _
GetType(Nullable(Of Date)),
GetType(DateTimePicker), _
New FrameworkPropertyMetadata(Date.Now,
New PropertyChangedCallback(AddressOf OnSelectedDateChanged),
New CoerceValueCallback(AddressOf CoerceDate)))
这是 CoerceDate
函数
Private Shared Function CoerceDate(ByVal d As DependencyObject,
ByVal value As Object) As Object
Dim dtpicker As DateTimePicker = CType(d, DateTimePicker)
Dim current As Date = CDate(value)
If current < dtpicker.MinimumDate Then
current = dtpicker.MinimumDate
End If
If current > dtpicker.MaximumDate Then
current = dtpicker.MaximumDate
End If
Return current
End Function
关注点
一件很难弄清楚的事情是如何将焦点从我的控件移开。结果,这很容易用一行代码实现
Me.MoveFocus(New TraversalRequest(FocusNavigationDirection.Previous))
可以改进的地方
日历的图像封装在控件中。有些人可能希望将图像作为属性公开。此外,虽然 SelectedDate
是可为空的,但我应该编写更多的代码来显示默认文本,当没有 SelectedDate
时。
历史
- 2010-12-02:首次尝试撰写本文
- 2011-09-08:添加了关于 Qwertie 版本的一个说明