Skip to content

ListViewBase

Header: winui/ui/collections/ListViewBase.hpp.

The shared base of ListView and TileView: a scrolling, virtualized, selectable collection of templated items. Each item sits in an item container that draws the hover, press and selection chrome.

The items are either plain strings (set_items(), shown as text by the default template) or an index range that an item template turns into content (set_item_template() and set_item_count()). Only the items in and near the viewport are realized, through the ForEachControl inside the Scroll (repeater(), scroll_view()). Report changes to the collection with insert_item() and remove_item() for strings, or the notify_*() calls for a template's collection. The selection then follows its items and the item container transitions play. The selection mode decides which gestures select. Groups, a header and footer, item click, drag reordering and saving the scroll position are all optional. The class cannot be constructed directly. Create a ListView or a TileView.

The list is one tab stop. The arrow keys move the focused item. In Extended mode, and in Single mode with single_selection_follows_focus(), the selection moves with it. Ctrl+A selects everything in Multiple and Extended mode, or clears the selection when everything is already selected.

Example:

auto  list = std::make_unique<ui::ListViewControl>();
list->set_items({"Apple", "Banana", "Cherry"});
list->set_selection_mode(ui::SelectionMode::Extended);
list->set_height(240.0f);
list->on_selection_changed([](std::optional<std::size_t> index)
                           { std::println("first selected: {}", index.value_or(0)); });

// A template's collection instead of strings:
struct Contact
{
    std::string name;
};
std::vector<Contact> contacts{{"Ada"}, {"Grace"}, {"Linus"}};
list->set_item_template([&contacts](std::size_t i) {
    return std::make_unique<ui::TextControl>(contacts[i].name);
});
list->set_item_count(contacts.size());

window.set_content(std::move(list));

ui::ListViewBase

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

The shared base of ListView and TileView: a scrolling, virtualized, selectable collection of templated items. Each item sits in an item container that draws the hover, press and selection chrome.

The items are either plain strings (set_items(), shown as text by the default template) or an index range that an item template turns into content (set_item_template() and set_item_count()). Only the items in and near the viewport are realized, through the ForEachControl inside the Scroll (repeater(), scroll_view()). Report changes to the collection with insert_item() and remove_item() for strings, or the notify_*() calls for a template's collection. The selection then follows its items and the item container transitions play. The selection mode decides which gestures select. Groups, a header and footer, item click, drag reordering and saving the scroll position are all optional. The class cannot be constructed directly. Create a ListView or a TileView.

The list is one tab stop. The arrow keys move the focused item. In Extended mode, and in Single mode with single_selection_follows_focus(), the selection moves with it. Ctrl+A selects everything in Multiple and Extended mode, or clears the selection when everything is already selected.

Example:

auto  list = std::make_unique<ui::ListViewControl>();
list->set_items({"Apple", "Banana", "Cherry"});
list->set_selection_mode(ui::SelectionMode::Extended);
list->set_height(240.0f);
list->on_selection_changed([](std::optional<std::size_t> index)
                           { std::println("first selected: {}", index.value_or(0)); });

// A template's collection instead of strings:
struct Contact
{
    std::string name;
};
std::vector<Contact> contacts{{"Ada"}, {"Grace"}, {"Linus"}};
list->set_item_template([&contacts](std::size_t i) {
    return std::make_unique<ui::TextControl>(contacts[i].name);
});
list->set_item_count(contacts.size());

window.set_content(std::move(list));

ItemTemplate

using ui::ListViewBase::ItemTemplate = Callback<std::unique_ptr<Element>(std::size_t index)>

Makes the content for item index and may choose a different look per item. Called when an item is realized. The list owns what it returns.

GroupHeaderTemplate

using ui::ListViewBase::GroupHeaderTemplate = Callback<std::unique_ptr<Element>(std::size_t group)>

Makes a group header's content, for group index group (group_key() names it).

~ListViewBase

~ListViewBase() override

ListViewBase

ListViewBase(const ListViewBase&) = delete

operator=

ListViewBase& operator=(const ListViewBase&) = delete

ListViewBase

ListViewBase(ListViewBase&&) = delete

operator=

ListViewBase& operator=(ListViewBase&&) = delete

items

const std::vector<std::string>& items() const

The string items. Empty when the items come from an item template.

set_items

void set_items(std::vector<std::string> items)

Replaces the items with a new list of strings. Nothing is selected afterwards. on_selection_changed() fires when something was selected before.

insert_item

void insert_item(std::size_t index, std::string item)

Inserts item before index. The selection stays on its items, and an AddRemoveTransition among the item container transitions plays.

add_item

void add_item(std::string item)

Appends item at the end.

remove_item

void remove_item(std::size_t index)

Removes the item at index, dropping it from the selection.

move_item

void move_item(std::size_t from, std::size_t to)

Moves the item at from to to, keeping its selection state.

set_item_template

void set_item_template(ItemTemplate item_template)

Sets the content template and rebuilds the realized items. nullptr, the default, shows each string of items() as text.

item_count

std::size_t item_count() const

How many items the list shows: items().size() for strings, else the set_item_count() value.

set_item_count

void set_item_count(std::size_t count)

Sets a collection of count items that only the template knows. Counts as a reset and clears items().

notify_inserted

void notify_inserted(std::size_t index, std::size_t count = 1)

Reports that count items were inserted at index in the template's collection.

notify_removed

void notify_removed(std::size_t index, std::size_t count = 1)

Reports that count items were removed at index. They leave the selection.

notify_replaced

void notify_replaced(std::size_t index, std::size_t count = 1)

Reports that count items at index changed in place. The template builds their content again.

notify_moved

void notify_moved(std::size_t from, std::size_t to)

Reports that the item at from moved to to. The selection moves with it.

notify_reset

void notify_reset()

Reports that the whole collection changed. Realized items are rebuilt and a ContentTransition among the item container transitions plays. Clears the selection, and fires on_selection_changed when there was one.

index_from_element

std::optional<std::size_t> index_from_element(const Element& inside) const

The item that inside, any element inside an item, belongs to. A handler inside a template, such as a context menu's Delete, uses it to find its item after inserts and removals moved it. Unset when inside is not in a realized item.

set_group_keys

void set_group_keys(std::vector<std::string> keys)

Files the items under group headers, one key per item in item order. The groups appear in the order their keys first appear, and the items keep their order within a group, so items with the same key need not be next to each other. An empty vector ungroups. An item past the end of keys goes under an empty key. Indices stay positions in the collection. Only the order on screen, which the arrow keys and Shift ranges follow, comes from the groups. In a TileView with a tile or stack layout, each header takes a line of its own.

group_keys

const std::vector<std::string>& group_keys() const

The keys set_group_keys() was given.

group_count

std::size_t group_count() const

How many groups the keys make; 0 when ungrouped.

group_key

const std::string& group_key(std::size_t group) const

Group group's key, as its header shows it. Empty past group_count().

set_group_header_template

void set_group_header_template(GroupHeaderTemplate header_template)

Sets the group header's content. nullptr shows the group's key as 20px text over a 1px divider.

sticky_group_headers

bool sticky_group_headers() const

Whether group headers are sticky; on by default. The current group's header stays pinned to the top of the viewport until the next header pushes it up.

set_sticky_group_headers

void set_sticky_group_headers(bool sticky)

Turns sticky group headers on or off.

set_header

template <typename T>
T* set_header(std::unique_ptr<T> header)

Sets content above the first item that scrolls with the items. Takes ownership, replaces any previous header, header_text() included, and returns a non-owning observer of the new one.

set_header_text

void set_header_text(std::string text)

Sets a plain-text header above the first item, in the group headers' text style, that scrolls with the items. Replaces any previous header. An empty text removes a text header.

header_text

const std::string& header_text() const

The text set_header_text() shows. Empty while there is none or the header is content.

Element* header() const

The current header, non-owning, or nullptr.

template <typename T>
T* set_footer(std::unique_ptr<T> footer)

Sets content after the last item that scrolls with the items. Takes ownership and returns a non-owning observer.

Element* footer() const

The current footer, non-owning, or nullptr.

selection_mode

SelectionMode selection_mode() const

The selection mode; Single by default.

set_selection_mode

void set_selection_mode(SelectionMode mode)

Sets the selection mode. None clears the selection, Single keeps one at most, and Multiple shows a check box in each item.

selected_index

std::optional<std::size_t> selected_index() const

The first selected item. Unset when nothing is selected.

set_selected_index

void set_selected_index(std::optional<std::size_t> index)

Selects index alone, clamped to the items, and scrolls it into view. Unset deselects all. No callback fires when nothing changes.

selected_items

std::vector<std::size_t> selected_items() const

The selected items, in index order.

set_selected_items

void set_selected_items(std::vector<std::size_t> indices)

Replaces the selection with the items at indices, in any order. Indices past the end are dropped, Single mode keeps the lowest one, and None selects nothing. Fires on_selection_changed() once, and only when the selection changed.

is_selected

bool is_selected(std::size_t index) const

Whether the item at index is selected.

select

void select(std::size_t index)

Adds an item to the selection, in Multiple and Extended mode.

deselect

void deselect(std::size_t index)

Removes the item at index from the selection.

select_all

void select_all()

Selects every item in Multiple and Extended mode, as Ctrl+A does.

deselect_all

void deselect_all()

Clears the selection.

single_selection_follows_focus

bool single_selection_follows_focus() const

Whether moving keyboard focus with the arrows also selects in Single mode; on by default.

set_single_selection_follows_focus

void set_single_selection_follows_focus(bool follows)

Turns selection-follows-focus on or off.

on_selection_changed

void on_selection_changed(Callback<void(std::optional<std::size_t>)> handler)

Called with selected_index() after the change. Fires for user gestures and programmatic changes, and only when the selection changed. Replaces any previous handler.

on_selected_index_shifted

void on_selected_index_shifted(Callback<void(std::optional<std::size_t>)> handler)

Called with the new index when the selected item stayed selected but an insert, removal or move before it changed selected_index(). It is not a selection change, so on_selection_changed does not fire. A two-way .selected_index uses it to follow the item. Replaces any previous handler.

is_item_click_enabled

bool is_item_click_enabled() const

Whether a click raises on_item_click(); off by default.

set_item_click_enabled

void set_item_click_enabled(bool enabled)

Turns on_item_click() on or off.

on_item_click

void on_item_click(Callback<void(std::size_t)> handler)

Called with the clicked item, before the click selects, while is_item_click_enabled(). Replaces any previous handler.

is_item_invoked_enabled

bool is_item_invoked_enabled() const

Whether on_item_invoked() is raised; off by default.

set_item_invoked_enabled

void set_item_invoked_enabled(bool enabled)

Turns on_item_invoked() on or off.

on_item_invoked

void on_item_invoked(Callback<void(std::size_t)> handler)

Called with the item on Enter or a double-click, and under SelectionMode::None also a click or Space, while is_item_invoked_enabled(). Raised after the gesture selects. Replaces any previous handler.

set_item_context_menu

void set_item_context_menu(Callback<std::vector<MenuItem>(std::size_t index)> menu)

Sets the context menu of item index. It is asked for on a right-click on the item, or on Shift+F10 or the Menu key while the item is the current one. The item is selected first, unless it already is or the selection mode is None. An empty list opens no menu. Replaces any previous one.

can_drag_items

bool can_drag_items() const

Whether an item dragged past the threshold starts a drag; off by default.

set_can_drag_items

void set_can_drag_items(bool can)

Turns item dragging on or off.

can_reorder_items

bool can_reorder_items() const

Whether a drag inside the list moves the item; off by default. Needs can_drag_items() and Element::allow_drop().

set_can_reorder_items

void set_can_reorder_items(bool can)

Turns reordering on or off.

on_drag_items_starting

void on_drag_items_starting(Callback<Decision(const DragItemsStartingArgs&)> handler)

A drag of items starts. Fill in the package's text or data, or cancel.

on_drag_items_completed

void on_drag_items_completed(Callback<void(const DragItemsCompletedArgs&)> handler)

A drag of items ended, with the items dragged and what the drop did (None when it was refused or canceled).

on_items_reordered

void on_items_reordered(Callback<void(const ItemsReorderedArgs&)> handler)

A drop inside the list moved item from to to, both positions in the collection after the move. A string list has already moved it. For a template's collection, move the data here. The list has already been told through notify_moved().

insertion_index_at

std::size_t insertion_index_at(Point position) const

Where a drop at position, in window coordinates, would insert: the index of the item it would go before. Past the middle of an item counts as after it.

scroll_into_view

void scroll_into_view(std::size_t index, ScrollIntoViewAlignment alignment = ScrollIntoViewAlignment::Default)

Scrolls so item index shows, by the least amount (Default) or to the top (Leading).

scroll_offset

float scroll_offset() const

The vertical scroll offset, DIPs. Horizontal for a vertical TileView.

scroll_view

ScrollControl* scroll_view() const

The inner Scroll, owned by the list.

repeater

ForEachControl* repeater() const

The inner ForEachControl that realizes the item containers, owned by the list. Its try_get_element() reaches a realized container by its index, counting group headers.

relative_scroll_position

std::string relative_scroll_position(Callback<std::string(std::size_t)> key_of) const

The key of the first item in view, from key_of, and how far it is scrolled past the top, as "key|offset".

set_relative_scroll_position

bool set_relative_scroll_position(const std::string& position, Callback<std::optional<std::size_t>(const std::string&)> index_of)

Scrolls back to what relative_scroll_position() described. index_of finds the item for a key and returns unset when there is none. Returns whether the item was found.

items_updating_scroll_mode

ItemsUpdatingScrollMode items_updating_scroll_mode() const

How the scroll position reacts to inserts and removes; KeepItemsInView by default.

set_items_updating_scroll_mode

void set_items_updating_scroll_mode(ItemsUpdatingScrollMode mode)

Sets the scroll mode. KeepLastItemInView makes a chat-style log follow its end.

set_panel_vertical_alignment

void set_panel_vertical_alignment(Alignment alignment)

Where the items sit vertically. Trailing puts a list shorter than its viewport at the bottom, as in a message log.

set_item_container_margin

void set_item_container_margin(const Thickness& margin)

Sets the margin around every item container, DIPs, and lays the items out again.

item_container_margin

const Thickness& item_container_margin() const

The margin around each item container.

set_item_horizontal_content_alignment

void set_item_horizontal_content_alignment(Alignment alignment)

How content sits horizontally in its container. Stretch in a ListView, Center in a TileView by default.

item_height

std::optional<float> item_height() const

A fixed container height, DIPs. Unset (the default) sizes each container to its content, at least 40 DIPs in a ListView.

set_item_height

void set_item_height(OptionalFloat height)

Sets the fixed container height, or clears it to size containers to their content. Lays the items out again.

set_background

void set_background(std::optional<Color> color)

Background behind the items, as a fixed color. nullopt is transparent.

set_background

void set_background(ThemeColor resource)

Background as a theme color, read again when the theme changes.

set_foreground

void set_foreground(std::optional<Color> color)

The default template's text color. nullopt uses the theme's text color.

set_foreground

void set_foreground(ThemeColor resource)

Foreground as a theme color.

set_border_brush

void set_border_brush(std::optional<Color> color)

The border color. nullopt draws no border.

set_border_brush

void set_border_brush(ThemeColor resource)

The border color as a theme color.

set_border_thickness

void set_border_thickness(const Thickness& thickness)

The border width on each side, DIPs. 0, the default, draws none.

set_padding

void set_padding(const Thickness& padding)

Padding inside the border, around the scrolling area.

item_transitions

const TransitionList& item_transitions() const

The item container transitions; empty by default. AddRemoveTransition plays on insert and removal, ContentTransition for a new collection, EntranceTransition when items first appear and RepositionTransition when they move.

set_item_transitions

void set_item_transitions(TransitionList transitions)

Sets the item container transitions. They apply to changes reported after the call.

focused

bool focused() const

Whether the list has keyboard focus.

current_item

std::optional<std::size_t> current_item() const

The item keyboard focus is on. Unset when there is none.

set_current_item

void set_current_item(std::size_t index)

Moves the keyboard focus cue to item index and scrolls it into view, leaving the selection as it is. An index past the end does nothing. The arrow keys go on from there.

focus_index

std::optional<std::size_t> focus_index() const

The item Tab steps through while the list is entered as a focus scope. Unset otherwise.

focusable

bool focusable() const override

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

automation_focus

Element* automation_focus() const override

The item the keyboard is on, so a screen reader reads it as the arrow keys move.

collect_focusables

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

Append focusable elements in tab order, so the Window can build a flat focus ring over the whole tree. The default pushes this element when focusable(), then recurses into every child for_each_child() lists. Override it when the ring differs from the children: a composite that is one tab stop pushes only itself, a focus scope stops recursing (see collect_scope_focusables()), a pager leaves out its hidden pages.

for_each_child

void for_each_child(ChildVisitor visit) const override

Lists the scroll view that holds the header, the items and the footer, and an open item context menu. The pinned group header is a drawn copy of a header already in the list and is not listed.

raise_context_requested

bool raise_context_requested(std::optional<Point> position) override

Runs the handler set above, if any; whether it took the request. A wrapper that stands in for the element it wraps in the tab ring (a flyout around its anchor) asks that element too.

scroll_info

std::optional<ScrollInfo> scroll_info() const override

This element's scrolling, or nullopt for one that does not scroll (the default). Scroll, VirtualList and ListView answer.

drag_enter

void drag_enter(const DragEventArgs& e) override

The drop events. drag_over() is asked first on the innermost drop target under the pointer, then on its drop targets up the tree until one accepts; every element asked has heard drag_enter() first and hears drag_leave() once the drag is no longer its business. The one that accepted gets drop(). A control overrides them; the defaults run the handlers set with on_drag_enter()/on_drag_over()/on_drag_leave()/on_drop().

drag_enter(): the drag has come over this element; drag_over() follows at once.

drag_over

DragResponse drag_over(const DragEventArgs& e) override

The drag is over this element: answer what a drop here would do. Asked when it arrives and at every move. The default runs the on_drag_over() handler, and refuses without one.

drag_leave

void drag_leave(const DragEventArgs& e) override

The drag left this element, was canceled over it, or was dropped on another target.

drop

void drop(const DragEventArgs& e) override

The pointer was released over this element while its drag_over() accepted. What the drop did is the operation it accepted.

drag_completed

void drag_completed(DataPackageOperation result) override

A drag this element started has ended. result is what the target did (None when the drag was canceled or dropped nowhere).

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.

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.

covers_children_at

bool covers_children_at(Point p) const override

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.

clear_dirty_override

void clear_dirty_override(DirtyFlags flags) override

This element's own part of clear_dirty(): clear any part it owns but leaves out of for_each_child() (a parked page, a hidden button), through that part's clear_dirty(). Default: nothing.

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.

collect_scope_focusables

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

The inner tab ring, built when this scope is entered: a scope's counterpart to collect_focusables(). A container that becomes a scope must stop recursing in collect_focusables() and recurse here instead (Expander is the worked example), since a child in both rings would be reachable without ever entering.

Three meaningful answers: - several elements: an ordinary container scope. Tab cycles them, Escape leaves. - this alone: an item-navigating scope. The control's items are not all elements (ListView creates its rows on demand and destroys them as they scroll out), so focus stays on the control and Tab is routed to scope_step() below. - nothing: there is nothing inside worth entering. Window doesn't enter, and the key that would have entered goes to this element's own handle_key(). That is how Enter expands a collapsed Expander that is marked as a scope.

The one walk that does not default to recursing through for_each_child(): being a scope is something a control opts into, and a default inner ring would make every container enterable while its children still sat in the outer ring too.

scope_step

bool scope_step(int delta) override

Move an item-navigating scope's own inner cursor one step: delta is +1 for Tab and -1 for Shift+Tab. Wrap and return true to keep focus inside the scope (Escape is then the way out, as for an ordinary container scope). Return false to let the step fall out, popping the scope and leaving focus on this control. Never called for a scope whose inner ring is real elements, since Window walks that ring itself.

set_scope_entered

void set_scope_entered(bool entered) override

Called by Window as this scope is entered (before its inner ring takes focus) and again as it is left, so a control can show and hide whatever inner cursor it draws. A container scope whose inner ring is real Elements usually needs nothing here, since the focused child draws its own focus ring, as it would anywhere else.

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.

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.

focus_changed

void focus_changed(bool focused) override

Keyboard focus arrived (true) or left (false); is_focused() already says so. The element is redrawn either way. No-op by default.

focus_ring_rect

Rect focus_ring_rect(const Theme& theme) const override

Inside the item the keyboard is on, cut to the part of it in view. Around the whole list when that item is out of view.

focus_ring_corner_radius

float focus_ring_corner_radius(const Theme& theme) const override

The ring's corner radius: the theme's control radius by default.

focus_ring_inside

bool focus_ring_inside() const override

Whether the ring goes inside focus_ring_rect() in every era, its outer edge on the rect. False by default, which leaves it to the theme. An item inside a viewport (a list row, a tab, a menu item) returns true, as does a control in a tight spot, so a neighbor or the viewport edge never cuts its ring.

automation_providers

void automation_providers(AutomationProviders& out) override

Lists what a client can do with this node: set out's field for each pattern this control implements now to this, through the provider interface it inherits privately (ui/Automation.hpp). A pattern that only applies in some states is an if. out arrives empty, and nothing is listed by default.

Example:

class Chip final : public ui::Element, private ui::InvokeProvider
{
protected:
    void automation_providers(ui::AutomationProviders& out) override
    {
        out.invoke = this;
    }

private:
    bool invoke() override
    {
        on_click_();
        return true;
    }
    ui::Callback<void()> on_click_;
};

struct ListViewDragPayload

What a ListView drag carries in DataPackage::data: the list it came from and the items dragged.

A drop target reads it back with std::any_cast<ListViewDragPayload>(&e.data.data).

Example:

void accept_drops(ui::ListViewControl* left, ui::ListViewControl* right)
{
    right->on_drop([=](const ui::DragEventArgs& e) {
        if (const auto* payload = std::any_cast<ui::ListViewDragPayload>(&e.data.data);
            payload != nullptr && payload->source == left)
        {
            right->insert_item(right->insertion_index_at(e.position), left->items()[payload->items.front()]);
            left->remove_item(payload->items.front());
        }
    });
}

Field Type Default
source const Element* nullptr The list the drag started from (non-owning).
items std::vector<std::size_t> The indices of the dragged items, in index order.

struct DragItemsStartingArgs

The arguments of ListViewBase::on_drag_items_starting().

The package already carries a ListViewDragPayload in data.data. A handler may add text for other drop targets, replace the payload, or return ui::Cancel to stop the drag.

Example:

auto list = std::make_unique<ui::ListViewControl>();
list->set_items({"Apple", "Banana", "Cherry"});
list->on_drag_items_starting([&](const ui::DragItemsStartingArgs& e) {
    if (e.items.size() > 1)
        return ui::Cancel; // single-item drags only
    e.data.text = list->items()[e.items.front()];
    return ui::Proceed;
});

Field Type Default
items std::vector<std::size_t> The indices of the items about to be dragged.
data DataPackage& The package the drag will carry. Fill in its text or data.

struct DragItemsCompletedArgs

What on_drag_items_completed gets once a drag out of a ListView or TileView ends.

Field Type Default
items std::vector<std::size_t> The indices of the dragged items.
result DataPackageOperation DataPackageOperation::None What the drop did; None when refused.

struct ItemsReorderedArgs

What on_items_reordered gets when a drop inside the list moved item from to to. Both are positions in the collection after the move.

Field Type Default
from std::size_t 0 Where the item was.
to std::size_t 0 Where it is now.

Enumerations

ScrollIntoViewAlignment

enum class ScrollIntoViewAlignment

Where ListViewBase::scroll_into_view() puts the item.

Value
Default The least scroll that shows the item.
Leading The item at the top of the viewport.

ItemsUpdatingScrollMode

enum class ItemsUpdatingScrollMode

How a list keeps its scroll position while items are inserted and removed.

Value
KeepItemsInView The first item in view stays in view (the default).
KeepScrollOffset The scroll offset stays put and the items move under it.
KeepLastItemInView A list scrolled to its end stays at its end as items arrive.

Tests

  • tests/test_list_view_base.cpp