AutoSuggestBox¶
Header: winui/ui/text/AutoSuggestBox.hpp. Spec: winui/ui/text/AutoSuggestBox.hpp.
A text box with a floating list of suggestions the app supplies as the user types, for search boxes and type-ahead pickers.
The control never filters. Handle on_text_changed(), and when the reason is AutoSuggestBoxTextChangeReason::UserInput, compute the matches and pass them to set_suggestions(). The popup opens whenever the box is focused and the list is non-empty.
Up and Down preview suggestions in the text. Stepping past either end restores what the user typed. A row click, or Enter on a highlighted row, fires on_suggestion_chosen(). Enter or a row click fires on_query_submitted(). Escape restores the typed text and closes the list. An optional query button (set_query_icon()) submits the typed text as a query.
Example:
static const std::vector<std::string> Cities{"Amsterdam", "Berlin", "Bern", "Zurich"};
auto box = std::make_unique<ui::AutoSuggestBoxControl>();
box->set_header("City");
box->set_placeholder_text("Search cities");
box->set_query_icon(ui::symbol_glyph(ui::Symbol::Find));
box->on_text_changed([b = box.get()](const ui::AutoSuggestBoxTextChangedArgs& args) {
if (args.reason != ui::AutoSuggestBoxTextChangeReason::UserInput)
return; // our own preview/revert writes; nothing to re-filter
std::vector<std::string> matches;
for (const std::string& city : Cities)
if (!args.text.empty() && city.starts_with(args.text))
matches.push_back(city);
b->set_suggestions(std::move(matches));
});
box->on_query_submitted([](const ui::AutoSuggestBoxQuerySubmittedArgs& args) {
// args.chosen_suggestion is unset for a free-typed query
});
window.set_content(std::move(box));
ui::AutoSuggestBox¶
A search field with a live suggestion list. Builds a ui::AutoSuggestBoxControl.
Usually .suggestions is bound to a property, .on_text_changed recomputes it as the user types, and .on_query_submitted runs the search.
Example:
const std::vector<std::string> titles{"Inbox", "Invoices", "Settings"};
ui::Property<std::vector<std::string>> matches;
window.set_content(ui::AutoSuggestBox{
.placeholder_text = "Search",
.suggestions = matches,
.query_icon = ui::symbol_glyph(ui::Symbol::Find),
.width = 300.0f,
.on_text_changed =
[&](const ui::AutoSuggestBoxTextChangedArgs& args)
{
if (args.reason == ui::AutoSuggestBoxTextChangeReason::UserInput)
{
std::vector<std::string> found;
for (const std::string& title : titles)
{
if (title.starts_with(args.text))
{
found.push_back(title);
}
}
matches = std::move(found);
}
},
.on_query_submitted = [](const ui::AutoSuggestBoxQuerySubmittedArgs& args)
{ std::println("Search for {}", args.query_text); },
});
Every field, in the order a designated initializer names them:
ui::AutoSuggestBox{
.header, .description, .error, .placeholder_text, .text, .suggestions, .query_icon, .style,
.margin, .width, .height, .min_width, .min_height, .max_width, .max_height,
.horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .enabled, .accessibility,
.on_text_changed, .on_suggestion_chosen, .on_query_submitted, .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 | |
|---|---|---|---|
header |
ui::Binding<std::string> |
The label above the control. Empty draws none. | |
description |
ui::Binding<std::string> |
Secondary text under the box, such as what to enter or why; empty draws none. Screen readers offer it as help text. | |
error |
ui::Binding<std::string> |
What is wrong with the value: non-empty shows it in the description's place in the critical color and draws the border in that color, and screen readers report the field invalid. The field shows exactly what it is given, so bind it to a check of the value and decide there when it shows (after the first submit, say). | |
placeholder_text |
ui::Binding<std::string> |
The hint shown while the text is empty. | |
text |
ui::TwoWayField<std::string> |
The query text in the box. | |
suggestions |
ui::Binding<std::vector<std::string>> |
The suggestion list. Bind it with ui::bind() and assign the property from .on_text_changed to update it as the user types. |
|
query_icon |
ui::Binding<ui::IconSource> |
The query button's icon: a Symbol, a glyph, a path or a picture; empty has no button. | |
on_text_changed |
ui::Callback<void(const ui::AutoSuggestBoxTextChangedArgs&)> |
The new text and why it changed. Recompute suggestions only for UserInput. | |
on_suggestion_chosen |
ui::Callback<void(std::size_t)> |
The user picked a suggestion: a row click, or Enter on the highlighted row. | |
on_query_submitted |
ui::Callback<void(const ui::AutoSuggestBoxQuerySubmittedArgs&)> |
Enter, a suggestion click or the query button. The chosen index is unset for typed text. | |
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::AutoSuggestBox> |
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, enabled, accessibility every spec carries (conventions).
build¶
Consumes the spec and returns the built ui::AutoSuggestBoxControl; the caller owns it.
ui::AutoSuggestBoxControl¶
Derives from ui::Element, ui::ValueProvider.
A text box with a floating list of suggestions the app supplies as the user types, for search boxes and type-ahead pickers.
The control never filters. Handle on_text_changed(), and when the reason is AutoSuggestBoxTextChangeReason::UserInput, compute the matches and pass them to set_suggestions(). The popup opens whenever the box is focused and the list is non-empty.
Up and Down preview suggestions in the text. Stepping past either end restores what the user typed. A row click, or Enter on a highlighted row, fires on_suggestion_chosen(). Enter or a row click fires on_query_submitted(). Escape restores the typed text and closes the list. An optional query button (set_query_icon()) submits the typed text as a query.
Example:
static const std::vector<std::string> Cities{"Amsterdam", "Berlin", "Bern", "Zurich"};
auto box = std::make_unique<ui::AutoSuggestBoxControl>();
box->set_header("City");
box->set_placeholder_text("Search cities");
box->set_query_icon(ui::symbol_glyph(ui::Symbol::Find));
box->on_text_changed([b = box.get()](const ui::AutoSuggestBoxTextChangedArgs& args) {
if (args.reason != ui::AutoSuggestBoxTextChangeReason::UserInput)
return; // our own preview/revert writes; nothing to re-filter
std::vector<std::string> matches;
for (const std::string& city : Cities)
if (!args.text.empty() && city.starts_with(args.text))
matches.push_back(city);
b->set_suggestions(std::move(matches));
});
box->on_query_submitted([](const ui::AutoSuggestBoxQuerySubmittedArgs& args) {
// args.chosen_suggestion is unset for a free-typed query
});
window.set_content(std::move(box));
AutoSuggestBoxControl¶
An empty box with no suggestions, header or query button.
AutoSuggestBoxControl¶
A box starting with text, which is also what Escape reverts to until the user types.
text¶
The text box's current text (UTF-8), including a previewed suggestion.
set_text¶
Replaces the text and moves the caret to the end. Doesn't fire on_text_changed() or change the suggestion list. It also doesn't change the text Escape restores, which only the user's typing sets.
suggestions¶
The list last passed to set_suggestions(), shown as-is in the popup.
set_suggestions¶
Replaces the shown suggestion list and clears the hover and keyboard highlight. Opens the popup when the control is focused and the new list is non-empty. Otherwise is_suggestion_list_open() stays as it was.
is_suggestion_list_open¶
Whether the suggestion popup is showing.
query_icon¶
The query button's icon; empty for no button.
set_query_icon¶
Shows a query button with this icon (such as Symbol::Find); a click on it submits the typed text with no suggestion chosen. An empty source, the default, has no button.
query_button_rect¶
The query button's rect in window DIPs, valid after arrange. Empty without a query icon.
placeholder_text¶
The hint shown while the text is empty.
set_placeholder_text¶
Sets the hint shown while the text is empty.
header¶
The header text above the box; empty for none.
set_header¶
The label above the control. Empty (the default) draws none and takes no room.
description¶
The secondary text under the box; empty (the default) draws none.
set_description¶
Sets the description. Empty draws none and takes no room.
error¶
What is wrong with the value, shown in the description's place in the critical color, with the border in the same color; empty (the default) shows the description.
set_error¶
Sets the error. Empty shows the description again.
automation_help_text_fallback¶
The description, or the error while one is set, is the help text a screen reader offers when accessibility().description is empty.
automation_invalid¶
Invalid while an error is set.
automation_name_fallback¶
The header names the control when accessibility().name does not.
on_text_changed¶
Fired after every change to the text, with the new text and the reason (AutoSuggestBoxTextChangeReason). set_text() doesn't fire it. When the reason is UserInput, filter the suggestions here and call set_suggestions().
on_suggestion_chosen¶
Fires with the suggestion's index when the user picks it with a row click, or with Enter while an arrow key has it highlighted. A highlight alone doesn't fire it. That shows in on_text_changed() with the reason AutoSuggestBoxTextChangeReason::Suggestion. Fires right before on_query_submitted(), with the suggestion already in the box.
on_query_submitted¶
Fired on Enter, a query button click, or after on_suggestion_chosen() for a row click. It fires even with nothing highlighted, for a typed query with no chosen index. The popup closes afterward.
focused¶
Whether the box has keyboard focus.
focusable¶
Focusable while enabled.
for_each_child¶
Visits the internal TextBox.
collect_focusables¶
One tab stop: the internal TextBox is part of this control, not a stop of its own.
automation_children¶
The internal TextBox is part of this control and not listed. While the suggestions show, lists them as a list of items. Selecting an item fills the box, and invoking it chooses it.
automation_focus¶
The highlighted suggestion while the list shows, so a screen reader reads it as the arrow keys move.
handle_context_menu¶
Shows Cut, Copy, Paste and Select All, with no spelling suggestions.
cursor_at¶
The text field's cursor over the text field: an I-beam, or an arrow over its buttons.
automation_role¶
Always AutomationRole::Edit.
caret_bounds¶
The inner text box's caret.
measure_override¶
Sizes exactly as the internal TextBox does, plus the header. The popup floats and does not add to the measured size.
arrange_override¶
Arranges the internal TextBox below the header.
pointer_override¶
Routes clicks to the text box, its delete button or the query button.
covers_children_at¶
Whether a part of this element drawn over its children is at p (a scroll bar over the content), so the element is hit there instead of a child. Default: false.
render_override¶
Draws the header, the text box and the query button.
enabled_changed¶
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.
focus_changed¶
Focus is forwarded to the internal TextBox; losing it closes the popup.
key_override¶
Up/Down walk the suggestions, Enter submits, Escape reverts; other keys edit the text.
text_override¶
Typed text goes to the internal TextBox and fires on_text_changed() with UserInput.
draws_focus_ring¶
None: the field shows focus with its accent border.
struct AutoSuggestBoxTextChangedArgs¶
What an AutoSuggestBox's on_text_changed gets: the text and what changed it.
| Field | Type | Default | |
|---|---|---|---|
text |
const std::string& |
The text now in the box. | |
reason |
AutoSuggestBoxTextChangeReason |
UserInput is the one to update the suggestions on. |
struct AutoSuggestBoxQuerySubmittedArgs¶
What on_query_submitted gets: the text, and the suggestion it came from, if any.
| Field | Type | Default | |
|---|---|---|---|
query_text |
const std::string& |
The submitted text. | |
chosen_suggestion |
std::optional<std::size_t> |
The suggestion's index; unset for typed text. |
Enumerations¶
AutoSuggestBoxTextChangeReason¶
Why the text box's text changed. Lets an on_text_changed handler tell the user's typing, which is worth filtering suggestions for, apart from the text this control writes itself.
| Value | |
|---|---|
UserInput |
The user typed, deleted or pasted text. |
ProgrammaticChange |
Escape, or an arrow key past either end of the list, restored the typed text. |
Suggestion |
A suggestion was put in the box, by an arrow key or a click. |
Tests¶
tests/test_auto_suggest_box.cpp