# Using the Dear ImGui Multi-Select API for List Selection Patterns

> Master Dear ImGui's multi select API for effortless list selection. Discover BeginMultiSelect and EndMultiSelect for advanced Ctrl+Shift+Box selection without manual state management.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-14

---

**The Dear ImGui multi-select API provides `BeginMultiSelect()` and `EndMultiSelect()` functions that handle complex selection bookkeeping—including Ctrl-click toggles, shift-range selection, and box-select—without requiring manual state management.**

Dear ImGui (ocornut/imgui) includes a dedicated multi-select API designed specifically for implementing robust list-selection patterns in graphical user interfaces. This API eliminates boilerplate code by automatically handling keyboard modifiers, range selections, and selection visuals through scope-based functions declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h).

## Core Architecture of the Multi-Select API

The multi-select system centers on the **ImGuiMultiSelectIO** structure, which acts as the communication bridge between Dear ImGui and your application code.

### ImGuiMultiSelectIO and State Management

The **ImGuiMultiSelectIO** struct, defined in [[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3076](https://github.com/ocornut/imgui/blob/master/imgui.h#L3076), stores the current selection state and pending selection requests. When you call `BeginMultiSelect()`, Dear ImGui creates a temporary `ImGuiMultiSelectTempData` object (stored in `g.MultiSelectTempData`) and returns a pointer to the IO struct that you use for the duration of the frame.

### BeginMultiSelect and EndMultiSelect

**`BeginMultiSelect(flags, selection_size, items_count)`**, declared in [[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 776](https://github.com/ocornut/imgui/blob/master/imgui.h#L776), initializes the multi-select scope and prepares the internal state. You must pair this with **`EndMultiSelect()`** ([[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) line 777](https://github.com/ocornut/imgui/blob/master/imgui.h#L777)), which flushes pending requests (such as `SetAll` or `SetRange`) and applies changes to your selection storage.

### Selection State Detection

The **IsItemToggledSelection()** function, documented in [[`imgui_widgets.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_widgets.cpp) at line 7539](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp#L7539), detects whether the user changed an item's selection state during the current frame. Call this immediately after `Selectable()` or `TreeNode()` to react to selection changes.

## Configuration Flags for Selection Behavior

Configure the multi-select behavior by passing **ImGuiMultiSelectFlags** to `BeginMultiSelect()`. The flag definitions reside in [[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around line 3044](https://github.com/ocornut/imgui/blob/master/imgui.h#L3044).

Key flags include:

- **SingleSelect**: Restricts selection to exactly one item at a time.
- **NoSelectAll**: Disables the Ctrl+A keyboard shortcut for selecting all items.
- **BoxSelect1d** and **BoxSelect2d**: Enable rectangular box selection for 1D lists or 2D grids.
- **ClearOnEscape**: Automatically clears the entire selection when the user presses Escape.

## Implementing List Selection Patterns

### Basic List Selection with Ctrl and Shift Support

To implement standard list selection, wrap your item loop with the multi-select scope and use `SetNextItemSelectionUserData()` to associate each item with an identifier:

```cpp
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d |
                              ImGuiMultiSelectFlags_ClearOnEscape;

ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, items.size());

for (int i = 0; i < items.size(); ++i) {
    ImGui::SetNextItemSelectionUserData(i);  // imgui.h line 282
    bool selected = ms_io->Selection.Contains(i);
    
    if (ImGui::Selectable(items[i].label, selected)) {
        // Click handling is managed automatically by the API
    }
    
    if (ImGui::IsItemToggledSelection()) {
        bool now_selected = ImGui::IsItemSelected();
        // Update your data model here
    }
}
ImGui::EndMultiSelect();

```

### Optimized Large Lists with ImGuiListClipper

For large datasets, combine multi-select with **ImGuiListClipper** as demonstrated in [[`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) lines 2868-2875](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L2868):

```cpp
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, item_count);
ImGuiListClipper clipper(item_count);

while (clipper.Step()) {
    for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; ++i) {
        ImGui::SetNextItemSelectionUserData(i);
        bool selected = ms_io->Selection.Contains(i);
        
        ImGui::Selectable(item_labels[i], selected);
        
        if (ImGui::IsItemToggledSelection()) {
            UpdateSelectionModel(i, ImGui::IsItemSelected());
        }
    }
}
ImGui::EndMultiSelect();

```

### Processing Selection Requests Manually

If your application uses custom storage backends, process raw selection requests directly using **ApplyRequests()**, declared in [[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3139](https://github.com/ocornut/imgui/blob/master/imgui.h#L3139):

```cpp
ImGui::ApplyRequests(ms_io);

// Iterate through ms_io->IO.Requests to handle ImGuiSelectionRequest types:
// - SetAll: Clear or select all items
// - SetRange: Select a contiguous range (used for shift-selection)

```

## Internal Implementation Details

When `BeginMultiSelect()` executes, Dear ImGui allocates temporary storage in `g.MultiSelectTempData` and links it to persistent state in `g.MultiSelectStorage`. Each `Selectable()` automatically checks for the `ImGuiItemFlags_IsMultiSelect` flag (set by the API) in [[`imgui_widgets.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_widgets.cpp) at line 8003](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp#L8003), forwarding interaction events to the multi-select logic.

The internal helpers **MultiSelectItemHeader** and **MultiSelectItemFooter**, declared in [[`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) around line 3680](https://github.com/ocornut/imgui/blob/master/imgui_internal.h#L3680), render selection visuals and inject the appropriate item flags automatically.

## Summary

- **Scope-based API**: Wrap list items with `BeginMultiSelect()` and `EndMultiSelect()` to activate multi-select behavior.
- **Automatic bookkeeping**: The API handles Ctrl-click toggling, shift-range selection, and box-select without manual state tracking.
- **User data association**: Use `SetNextItemSelectionUserData()` to identify items for range and box selection operations.
- **Change detection**: Call `IsItemToggledSelection()` after item widgets to detect selection changes and update your data model.
- **Performance optimization**: Combine with `ImGuiListClipper` for efficient handling of large datasets, following the patterns in [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) lines 2716-3057.

## Frequently Asked Questions

### How do I enable box selection in my Dear ImGui list?

Pass the **ImGuiMultiSelectFlags_BoxSelect2d** flag to `BeginMultiSelect()` for two-dimensional selection, or **ImGuiMultiSelectFlags_BoxSelect1d** for one-dimensional lists. These flags allow users to click and drag a rectangle to select multiple items automatically without additional code.

### What is the difference between IsItemToggledSelection and IsItemSelected?

**IsItemToggledSelection()** returns true only during the frame when the user actually changed the item's selection state, making it ideal for triggering data model updates. **IsItemSelected()** merely reports the current selection state and can be called anytime to query whether an item is currently selected.

### How do I handle selection in a list with millions of items?

Use **ImGuiListClipper** to render only visible items, as shown in [[`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp)](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp). Call `SetNextItemSelectionUserData()` with the actual item index (not the visible index) so that range selections work correctly across the entire dataset, not just the visible portion.

### Where can I find complete working examples of the multi-select API?

The Dear ImGui repository contains comprehensive demonstrations in [[`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp) lines 2716-3057](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp#L2716), including examples of basic lists, clipped large lists, and dynamic item deletion scenarios.