Skip to content

CalendarDatePicker

Header: winui/ui/datetime/CalendarDatePicker.hpp. Spec: winui/ui/datetime/CalendarDatePicker.hpp.

A field that shows a date and opens a CalendarView under itself to pick one.

The field shows the date in the short date pattern of regional_date_format() (or its own date_format), and the placeholder text while no date is picked. A click, Enter, Space, Alt+Down or F4 opens the calendar. Picking a day sets the date and closes it, clicking the picked day again clears the date and keeps it open, and Escape or a click outside closes it without a change. calendar() is the CalendarView in the popup, for its range, first day of the week and blackout dates.

The field follows the theme's era: Fluent's field with a calendar glyph, and in the classic, Luna and Aero eras the era's drop-down field with the era's month calendar under it.

ui::CalendarDatePicker is the declarative form.

Example:

ui::CalendarDatePickerControl picker;
picker.set_header("Arrival");
picker.calendar().set_date_range(ui::today(), std::nullopt); // nothing in the past
picker.on_date_changed([](std::optional<std::chrono::year_month_day> date)
                       { std::printf("%s\n", date ? "picked" : "cleared"); });

ui::CalendarDatePicker

The declarative form of CalendarDatePickerControl: a date field with a calendar.

Example:

ui::Property<std::optional<std::chrono::year_month_day>> arrival;

window.set_content(ui::CalendarDatePicker{
    .header           = "Arrival",
    .placeholder_text = "Pick a date",
    .date             = arrival,
    .min_date         = ui::today(),
});

Every field, in the order a designated initializer names them:

ui::CalendarDatePicker{
    .header, .description, .placeholder_text, .date, .min_date, .max_date, .date_format,
    .first_day_of_week, .today_highlighted, .out_of_scope_enabled, .group_label_visible,
    .is_calendar_open, .style, .margin, .width, .height, .min_width, .min_height, .max_width,
    .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .enabled,
    .accessibility, .on_date_changed, .on_opened, .on_closed, .on_pointer_entered,
    .on_pointer_exited, .on_got_focus, .on_lost_focus, .on_key_down, .on_wheel, .control,
    .is_blackout
}

Fields, in declaration order (designators must follow it):

Field Type Default
header ui::Binding<std::string> The label above the field. Empty shows none.
description ui::Binding<std::string> The hint below the field. Empty shows none.
placeholder_text ui::Binding<std::optional<std::string>> What the field shows while no date is picked; unset is "Pick a date".
date ui::TwoWayField<std::optional<std::chrono::year_month_day>> The picked date; unset until one is picked.
min_date ui::Binding<std::optional<std::chrono::year_month_day>> The first date the calendar offers; unset is January 1, 100 years before today.
max_date ui::Binding<std::optional<std::chrono::year_month_day>> The last date the calendar offers; unset is December 31, 100 years after today.
date_format ui::Binding<std::optional<std::string>> The pattern the field writes the date with (DateFormatSymbols); unset is the short date.
first_day_of_week ui::Binding<std::optional<std::chrono::weekday>> The day the calendar's weeks start on; unset follows regional_date_format().
today_highlighted ui::Binding<bool> {true} Whether the calendar draws today highlighted.
out_of_scope_enabled ui::Binding<bool> {true} Whether the calendar dims the neighboring months' days.
group_label_visible ui::Binding<bool> {false} Whether the calendar names the month on its first day.
is_calendar_open ui::TwoWayField<bool> {false} Whether the calendar is open.
on_date_changed ui::Callback<void(std::optional<std::chrono::year_month_day>)> The new date (unset when cleared), from the calendar or a bound value.
on_opened ui::Action The calendar opened.
on_closed ui::Action The calendar closed.
on_pointer_entered ui::Action The pointer moved onto the control.
on_pointer_exited ui::Action The pointer left the control.
on_got_focus ui::Action Keyboard focus arrived on the control, or on anything inside it, from outside it.
on_lost_focus ui::Action Keyboard focus left the control and everything inside it.
on_key_down ui::Callback<ui::Handling(const ui::KeyEvent&)> A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()).
on_wheel ui::Callback<ui::Handling(const ui::PointerEvent&)> A wheel turn over the control; ui::Handled stops it there (Element::on_wheel()).
control ui::ControlOut<ui::CalendarDatePicker> Out: the handle that receives the built control.
is_blackout ui::Callback<bool(std::chrono::year_month_day)> Marks dates the calendar won't let be picked; unset blocks none.

Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, enabled, accessibility every spec carries (conventions).

build

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::CalendarDatePickerControl; the caller owns it.

ui::CalendarDatePickerControl

Derives from ui::Element, ui::InvokeProvider, ui::ValueProvider.

A field that shows a date and opens a CalendarView under itself to pick one.

The field shows the date in the short date pattern of regional_date_format() (or its own date_format), and the placeholder text while no date is picked. A click, Enter, Space, Alt+Down or F4 opens the calendar. Picking a day sets the date and closes it, clicking the picked day again clears the date and keeps it open, and Escape or a click outside closes it without a change. calendar() is the CalendarView in the popup, for its range, first day of the week and blackout dates.

The field follows the theme's era: Fluent's field with a calendar glyph, and in the classic, Luna and Aero eras the era's drop-down field with the era's month calendar under it.

ui::CalendarDatePicker is the declarative form.

Example:

ui::CalendarDatePickerControl picker;
picker.set_header("Arrival");
picker.calendar().set_date_range(ui::today(), std::nullopt); // nothing in the past
picker.on_date_changed([](std::optional<std::chrono::year_month_day> date)
                       { std::printf("%s\n", date ? "picked" : "cleared"); });

CalendarDatePickerControl

CalendarDatePickerControl()

An empty picker showing its placeholder.

~CalendarDatePickerControl

~CalendarDatePickerControl() override

CalendarDatePickerControl

CalendarDatePickerControl(const CalendarDatePickerControl&) = delete

operator=

CalendarDatePickerControl& operator=(const CalendarDatePickerControl&) = delete

date

std::optional<std::chrono::year_month_day> date() const

The picked date; unset until one is picked.

set_date

void set_date(std::optional<std::chrono::year_month_day> date)

Sets the date, clamped to the calendar's range. Raises the change callback when it differs.

on_date_changed

void on_date_changed(Callback<void(std::optional<std::chrono::year_month_day>)> handler)

Called after the date changed, from the calendar or a setter, with the new date.

set_header

void set_header(std::string text)

The label above the field. Empty shows none.

set_description

void set_description(std::string text)

The hint below the field. Empty shows none.

set_placeholder_text

void set_placeholder_text(std::optional<std::string> text)

What the field shows while no date is picked; unset is "Pick a date" (ui::strings()).

set_date_format

void set_date_format(std::optional<std::string> pattern)

The pattern the date is written with (DateFormatSymbols); unset is the short date.

shown_text

std::string shown_text() const

The text the field shows now: the date, or the placeholder.

is_calendar_open

bool is_calendar_open() const

Whether the calendar is open.

set_calendar_open

void set_calendar_open(bool open)

Opens or closes the calendar.

on_calendar_open_changed

void on_calendar_open_changed(Callback<void(bool)> handler)

Called after the calendar opened (true) or closed (false).

calendar

CalendarViewControl& calendar()

The calendar the popup shows. It stays a CalendarView in single selection.

focusable

bool focusable() const override

Whether this element can take keyboard focus (a leaf control opts in).

automation_role

AutomationRole automation_role() const override

What screen readers and other assistive tools see of this node: the role, name, help text and children here, and what a client can do with the node through the providers automation_providers() lists (ui/Automation.hpp).

automation_role() is the role this node reports; Group by default.

automation_name_fallback

std::string automation_name_fallback() const override

automation_name()'s fallback when accessibility().name is empty. Default: no inherent name, correct for controls with no visible text of their own (Slider, ProgressBar), which need an explicit accessibility().name from the caller. A control with its own visible text (Button, CheckBox, TextControl, ...) overrides this to return it.

automation_children

void automation_children(std::vector<Element*>& out) const override

The children an automation client sees under this node, immediate children only. A client walks the tree one level at a time, and the parent comes from parent(). Defaults to every child for_each_child() lists. Override it only to show a client something else: the children in a different order, or without parts that are only decoration. A composite that is one automation node lists nothing.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

Implement these instead of measure() and arrange(). The base class has already applied margin, size limits and alignment by the time these run. measure_override() is pure (every concrete Element must size itself); arrange_override() defaults to a no-op since most leaves need nothing beyond having bounds() set, which the base already did.

arrange_override

void arrange_override(const Rect& final_rect, const ArrangeContext& context) override

Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

What the control draws, in layout coordinates; render() has already applied the visual layer. A container draws its children through their render(), never their render_override().

pointer_override

bool pointer_override(const PointerEvent& e) override

A pointer event for this element: the element under the pointer, one inside it that did not handle the event, or the element holding the capture. The position is in layout coordinates (handle_pointer()). Return true when the event did something here, and it goes no further up; a handled press also captures the pointer until its release. A control that acts on a press (a click, a toggle, a caret placed, a drag started) returns true for the press and its release, so a list row or a card around it does not act on the same click. Default: false.

key_override

bool key_override(const KeyEvent& e) override

A key for this element: the focused one, or one inside it that did not handle it. Return true when the key did something here, and it goes no further; false lets it bubble on to the parent and then to the shortcuts, a dialog's default button and arrow-key focus moves. Default: false.

enabled_changed

void enabled_changed() override

is_enabled() flipped, through set_enabled() here or on an ancestor, or a move to another parent. Drop any press or hover state. The element is redrawn either way. No-op by default.

tick_override

void tick_override(Duration delta) override

This element's own part of tick(): a clock of its own (ToolTip's hover delay, an animation's phase, a caret blink). Runs after the visual layer has advanced and before the children are ticked, which tick() does by itself. Tick only parts that for_each_child() does not list here. Default: nothing.

Tests

  • tests/test_calendar_date_picker.cpp