日历、日期和时间控件

日期和时间控件提供标准、本地化的方法,让用户在应用中查看和设置日期和时间值。 本文提供了设计指南,可帮助你选取正确的控件。

WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码

应使用哪个日期或时间控件?

有四个日期和时间控件可供选择;使用的控件取决于你的方案。 使用此信息可以选取在应用中使用的正确控件。

控制 示例 说明
日历视图 日历视图示例 用于从始终可见的日历中选取单个日期或日期范围。
日历日期选取器 日历日期选取器的屏幕截图。 用于从上下文日历中选择单个日期。
日期选取器 日期选取器示例 用于在上下文信息不重要时选取单个已知日期。
时间选择器 时间选取器示例 用于选取单个时间值。

日历视图

CalendarView 允许用户查看日历并与之交互,日历可以按月、年或十年导航。 用户可以选择单个日期或日期范围。 它没有选取器图面,日历始终可见。

日历视图由 3 个单独的视图组成:月视图、年份视图和十年视图。 默认情况下,它从月份视图打开开始,但你可以将任何视图指定为启动视图。

三个日历视图的屏幕截图,其中分别显示月视图、年视图和十年视图。

  • 如果需要让用户选择多个日期,则必须使用 CalendarView
  • 如果需要让用户仅选取单个日期并且不需要日历始终可见,请考虑使用 CalendarDatePickerDatePicker 控件。

日历日期选取器

CalendarDatePicker 是一个下拉式控件,该控件已针对从日历视图中选取某个日期进行了优化,尤其是能够显示诸如星期几或丰富的日历信息等上下文信息。 可以修改日历以提供其他上下文或限制可用日期。

如果尚未设置日期,入口点将显示占位符文本;否则,它将显示所选日期。 当用户选择入口点时,日历视图将展开供用户选择日期。 日历视图覆盖其他 UI;它不会以这种方式推送其他 UI。

日历日期选取器的屏幕截图,其中显示了空的“选择日期”文本框,并通过其下方的日历填充了一个日期。

  • 将日历日期选取器用于选择约会或出发日期等内容。

日期选取器

DatePicker 控件提供了一种标准化的方式来选择特定日期。

入口点显示所选日期,当用户选择入口点时,选取器图面将从中间垂直展开,供用户选择。 日期选取器覆盖其他 UI;它不会以这种方式推送其他 UI。

日期选取器扩展示例

  • 使用日期选取器允许用户选取已知日期,例如出生日期,其中日历上下文不重要。

时间选择器

TimePicker 用于为约会或出发时间等内容选择单个时间值。 它是由用户或代码设置的静态显示,但它不会更新以显示当前时间。

入口点显示所选时间,当用户选择入口点时,选取器图面从中间垂直展开,供用户选择。 时间选取器覆盖其他 UI;它不会以这种方式推送其他 UI。

时间选取器扩展的示例

  • 使用时间选取器让用户选取单个时间值。

创建日期或时间控件

有关特定于每个日期和时间控件的信息和示例,请参阅这些文章。

将日期选取器和时间选取器结合使用

此示例演示如何结合使用 DatePickerTimePicker,使用户能够选择其到达日期和时间。 可以处理 SelectedDateChangedSelectedTimeChanged 事件以更新名为 arrivalDateTime 的单个 DateTime 实例。 用户还可以在设置日期和时间选取器后将其清除。

日期选取器、时间选择器、按钮和文本标签。

<StackPanel>
    <DatePicker x:Name="arrivalDatePicker" Header="Arrival date"
                DayFormat="{}{day.integer} ({dayofweek.abbreviated})"
                SelectedDateChanged="ArrivalDatePicker_SelectedDateChanged"/>
    <StackPanel Orientation="Horizontal">
        <TimePicker x:Name="arrivalTimePicker" Header="Arrival time"
                MinuteIncrement="15"
                SelectedTimeChanged="ArrivalTimePicker_SelectedTimeChanged"/>
        <Button Content="Clear" Click="ClearDateButton_Click"
                VerticalAlignment="Bottom" Height="30" Width="54"/>
    </StackPanel>
    <TextBlock x:Name="arrivalText" Margin="0,12"/>
</StackPanel>
public sealed partial class MainPage : Page
{
    DateTime arrivalDateTime;

    public MainPage()
    {
        this.InitializeComponent();

        // Set minimum to the current year and maximum to five years from now.
        arrivalDatePicker.MinYear = DateTimeOffset.Now;
        arrivalDatePicker.MaxYear = DateTimeOffset.Now.AddYears(5);
    }

    private void ArrivalTimePicker_SelectedTimeChanged(TimePicker sender, TimePickerSelectedValueChangedEventArgs args)
    {
        if (arrivalTimePicker.SelectedTime != null)
        {
            arrivalDateTime = new DateTime(arrivalDateTime.Year, arrivalDateTime.Month, arrivalDateTime.Day,
                                           args.NewTime.Value.Hours, args.NewTime.Value.Minutes, args.NewTime.Value.Seconds);
        }
        arrivalText.Text = arrivalDateTime.ToString();
    }

    private void ArrivalDatePicker_SelectedDateChanged(DatePicker sender, DatePickerSelectedValueChangedEventArgs args)
    {
        if (arrivalDatePicker.SelectedDate != null)
        {
            if (VerifyDateIsFuture((DateTimeOffset)arrivalDatePicker.SelectedDate) == true)
            {
                arrivalDateTime = new DateTime(args.NewDate.Value.Year, args.NewDate.Value.Month, args.NewDate.Value.Day,
                                               arrivalDateTime.Hour, arrivalDateTime.Minute, arrivalDateTime.Second);
                arrivalText.Text = arrivalDateTime.ToString();
            }
            else
            {
                arrivalDatePicker.SelectedDate = null;
                arrivalText.Text = "Arrival date must be later than today.";
            }
        }
    }

    private bool VerifyDateIsFuture(DateTimeOffset date)
    {
        if (date > DateTimeOffset.Now)
        {
            return true;
        }
        return false;
    }

    private void ClearDateButton_Click(object sender, RoutedEventArgs e)
    {
        arrivalDateTime = new DateTime();
        arrivalDatePicker.SelectedDate = null;
        arrivalTimePicker.SelectedTime = null;
        arrivalText.Text = string.Empty;
    }
}

全球化

XAML 日期控件支持 Windows 支持的每个日历系统。 这些日历在 Windows.Globalization.CalendarIdentifiers 类中指定。 每个控件对应用的默认语言使用正确的日历,也可以将 CalendarIdentifier 属性设置为使用特定的日历系统。

时间选取器控件支持 Windows.Globalization.ClockIdentifiers 类中指定的每个时钟系统。 可以将 ClockIdentifier 属性设置为使用 12 小时制或 24 小时制。 属性的类型为 String,但必须使用对应于 ClockIdentifiers 类的静态字符串属性的值。 这些是:12Hour(字符串“12HourClock”)和20FourHour(字符串“24HourClock”)。 “12HourClock”是默认值。

DateTime 和 Calendar 值

XAML 日期和时间控件中使用的日期对象具有不同的表示形式,具体取决于编程语言。

相关概念是 Calendar 类,它影响日期在上下文中的解释方式。 所有Windows 运行时应用都可以使用 Windows.Globalization.Calendar 类。 C# 和 Visual Basic 应用也可以使用 System.Globalization.Calendar 类,该类具有非常相似的功能。 (Windows 运行时应用可以使用基本 .NET 日历类,但不能使用特定实现;例如,GregorianCalendar。

.NET 还支持名为 DateTime 的类型,该类型可隐式转换为 DateTimeOffset。 因此,你可能会在 .NET 代码中看到一种“DateTime”类型,该类型用于设置真正为 DateTimeOffset 的值。 有关 DateTime 和 DateTimeOffset 之间的差异的详细信息,请参阅 DateTimeOffset 类中的备注。

注意

获取日期对象的属性不可以设置为 XAML 属性字符串,因为 Windows 运行时 XAML 解析器不具有用于将字符串转换为日期(作为 DateTime/DateTimeOffset 对象)的转换逻辑。 通常在代码中设置这些值。 另一个可行的方法是定义可用作数据对象或在数据上下文中可用的日期,然后将该属性设置为引用 {Binding} 标记扩展表达式的 XAML 属性,以便可以作为数据访问该日期。

获取示例代码

面向开发人员 (XAML)