NavigationFrame¶
Header: winui/ui/navigation/NavigationFrame.hpp. Spec: winui/ui/navigation/NavigationFrame.hpp.
A page host with a back and forward stack: shows one page at a time, built by a PageFactory on each navigation, and animates between pages with a NavigationTransition.
The frame owns the page on screen, and with NavigationCacheMode::Enabled also the cached pages on its stacks. Layout, input, focus and rendering pass straight through to the page on screen. While a transition plays, the leaving page is drawn under the arriving one and neither takes pointer input. The declarative form is ui::NavigationFrame, navigated through its .control.
Example:
auto frame_owned = std::make_unique<ui::NavigationFrameControl>();
frame_owned->set_content_transitions({ui::NavigationTransition{}});
frame_owned->on_navigated([](const ui::NavigationEventArgs& e) {
if (e.mode == ui::NavigationMode::Back)
std::println("came back");
});
ui::NavigationFrameControl* frame = window.set_content(std::move(frame_owned));
frame->navigate([] { return std::make_unique<ui::TextControl>("Home"); });
frame->navigate([] { return std::make_unique<ui::TextControl>("Settings"); },
ui::ZoomPageTransition{});
if (frame->can_go_back())
frame->go_back(); // "Home" again, rebuilt by its factory
// Or declaratively, taking the frame through .control:
ui::Control<ui::NavigationFrame> page_host;
window.set_content(ui::NavigationFrame{
.content_transitions = {ui::NavigationTransition{}},
.control = page_host,
});
page_host->navigate([] { return ui::Text{.text = "Home"}; });
ui::NavigationFrame¶
A page host with a back stack. Builds a ui::NavigationFrameControl. The name ui::Frame belongs to the window's frame style. Navigate it through .control, since a page is a factory and navigation is an action on the frame.
Example:
ui::Control<ui::NavigationFrame> frame;
ui::Property<bool> back_enabled{false};
window.set_content(ui::NavigationFrame{
.content_transitions = { ui::NavigationTransition{} },
.on_navigated = [&](const ui::NavigationEventArgs&) { back_enabled = frame->can_go_back(); },
.control = frame,
});
frame->navigate([] { return ui::Text{.text = "Home"}; });
frame->navigate([] { return ui::Text{.text = "Settings"}; }, ui::ZoomPageTransition{});
frame->go_back(); // "Home" again, rebuilt by its factory
Every field, in the order a designated initializer names them:
ui::NavigationFrame{
.content_transitions, .style, .margin, .width, .height, .min_width, .min_height,
.max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip,
.accessibility, .on_navigated, .on_pointer_entered, .on_pointer_exited, .on_got_focus,
.on_lost_focus, .on_key_down, .on_wheel, .control
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
content_transitions |
ui::Binding<ui::TransitionList> |
The transitions; a NavigationTransition animates navigation. | |
on_navigated |
ui::Callback<void(const ui::NavigationEventArgs&)> |
Called after the new page is in place. | |
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. A control with nothing focusable in it never gets focus, and never raises this. | |
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, before the control scrolls; ui::Handled stops it there (Element::on_wheel()). | |
control |
ui::ControlOut<ui::NavigationFrame> |
Out: the handle that receives the built control. |
Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, accessibility every spec carries (conventions).
build¶
Consumes the spec and returns the built ui::NavigationFrameControl; the caller owns it.
ui::NavigationFrameControl¶
Derives from ui::Element.
A page host with a back and forward stack: shows one page at a time, built by a PageFactory on each navigation, and animates between pages with a NavigationTransition.
The frame owns the page on screen, and with NavigationCacheMode::Enabled also the cached pages on its stacks. Layout, input, focus and rendering pass straight through to the page on screen. While a transition plays, the leaving page is drawn under the arriving one and neither takes pointer input. The declarative form is ui::NavigationFrame, navigated through its .control.
Example:
auto frame_owned = std::make_unique<ui::NavigationFrameControl>();
frame_owned->set_content_transitions({ui::NavigationTransition{}});
frame_owned->on_navigated([](const ui::NavigationEventArgs& e) {
if (e.mode == ui::NavigationMode::Back)
std::println("came back");
});
ui::NavigationFrameControl* frame = window.set_content(std::move(frame_owned));
frame->navigate([] { return std::make_unique<ui::TextControl>("Home"); });
frame->navigate([] { return std::make_unique<ui::TextControl>("Settings"); },
ui::ZoomPageTransition{});
if (frame->can_go_back())
frame->go_back(); // "Home" again, rebuilt by its factory
// Or declaratively, taking the frame through .control:
ui::Control<ui::NavigationFrame> page_host;
window.set_content(ui::NavigationFrame{
.content_transitions = {ui::NavigationTransition{}},
.control = page_host,
});
page_host->navigate([] { return ui::Text{.text = "Home"}; });
NavigationFrameControl¶
An empty frame: no page, empty stacks, and no transitions (navigation is immediate).
navigate¶
bool navigate(PageFactory page, std::optional<PageTransition> transition = std::nullopt, NavigationCacheMode cache = NavigationCacheMode::Disabled)
Shows a new page, pushing the one on screen onto the back stack and clearing the forward stack. transition overrides the NavigationTransition's default. Returns false and does nothing for an empty factory or one that builds nothing.
go_back¶
Moves the page on screen onto the forward stack, shows the top of the back stack and plays the transition backwards. The transition is the leaving entry's own unless transition is given. Returns false when the back stack is empty.
go_forward¶
Moves the page on screen back onto the back stack and shows the top of the forward stack, with the transition it was first navigated with. Returns false when the forward stack is empty.
can_go_back¶
Whether the back stack is not empty.
can_go_forward¶
Whether the forward stack is not empty: a go_back() has not been followed by a navigate() since.
back_stack_depth¶
How many pages go_back() can return to.
content¶
The page on screen, or nullptr before the first navigation.
leaving¶
The page going away while its navigation transition plays, or nullptr.
content_transitions¶
The transitions; a NavigationTransition here animates navigation.
set_content_transitions¶
Replaces the transitions; takes effect from the next navigation.
on_navigated¶
Fired after the new page is in place, before it is laid out. A page's arrival work, like starting a connected animation, goes here.
on_navigating_from¶
Fired before a navigation, with the page about to leave. The page is still on screen and laid out, so this is where to prepare a connected animation from it.
for_each_child¶
Visits the page on screen only. A leaving page is never focusable, owns no popups and is not an automation child, and a NativeControl on a page left behind is hidden. clear_dirty() and tick_override() reach the leaving page too.
measure_override¶
The desired size of the page on screen, or zero with no page. The leaving page is measured too.
arrange_override¶
Both the page on screen and the leaving page fill the frame's whole rect.
render_override¶
The leaving page, then the page on screen over it.
clear_dirty_override¶
Clears the frame's flags and those of both pages, the leaving one included.
tick_override¶
Plays the leaving page's exit. Once it has finished, the page is destroyed, or kept on its stack entry if that entry caches it.
class PageFactory¶
Derives from ui::Callback< std::unique_ptr< Element >()>.
Builds a page. Called on every navigation to it, and again on going back to it unless it was cached. A callable returning a std::unique_ptr to an Element works, and so does one returning a spec ([] { return ui::Text{.text = "Home"}; }), which is built each time.
PageFactory¶
No factory; navigate() refuses it.
PageFactory¶
template <typename F>
PageFactory(F page)
requires std::invocable<F&> && (!std::convertible_to<std::invoke_result_t<F&>, std::unique_ptr<Element>>) && std::convertible_to<std::invoke_result_t<F&>, Spec>
A callable that returns a spec, built into the page on each call.
struct NavigationEventArgs¶
What the frame's on_navigated() handler gets: the page now on screen, not laid out yet, and how it got there.
| Field | Type | Default | |
|---|---|---|---|
content |
Element* |
nullptr |
The new page; owned by the frame, valid until it navigates away from it. |
mode |
NavigationMode |
NavigationMode::New |
Whether it arrived by navigate(), go_back() or go_forward(). |
struct NavigatingFromEventArgs¶
What the frame's on_navigating_from() handler gets: the page about to leave, still on screen and laid out, and how the frame is leaving it.
| Field | Type | Default | |
|---|---|---|---|
page |
Element& |
The page on screen now. | |
mode |
NavigationMode |
NavigationMode::New |
Leaving by navigate(), go_back() or go_forward(). |
Enumerations¶
NavigationMode¶
How the page on screen got there.
| Value | |
|---|---|
New |
navigate(): a new page, the old one pushed onto the back stack. |
Back |
go_back(): the top of the back stack came back. |
Forward |
go_forward(): the top of the forward stack came back. |
NavigationCacheMode¶
Whether a page on the back stack is kept alive (Enabled) or built again by its factory when it is gone back to (Disabled, the default).
| Value | |
|---|---|
Disabled |
The page is destroyed when left and rebuilt by its factory on return. |
Enabled |
The page instance is kept on the stack and shown again as it was left. |
Tests¶
tests/test_navigation_frame.cpp