65.9K
CodeProject 正在变化。 阅读更多。
Home

与 Winforms 中的 DateTimePicker 一样的 WPF DateTimePicker

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (11投票s)

2010 年 12 月 2 日

CPOL

2分钟阅读

viewsIcon

138234

downloadIcon

6527

与 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 - 可以选择的最大日期值

有趣的是,SelectedDateMinimumDate 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 版本的一个说明
© . All rights reserved.