diff --git a/components/grid/events.md b/components/grid/events.md index bd94f77b15..b0b59d932b 100644 --- a/components/grid/events.md +++ b/components/grid/events.md @@ -1058,10 +1058,14 @@ Make sure to update the current page size when using the event. Fires when [row selection is enabled]({%slug grid-selection-overview%}#enable-row-or-cell-selection) and the user selects or deselects one row or multiple rows, depending on the [selection mode]({%slug grid-selection-overview%}#use-single-or-multiple-selection). +Visit the [Grid Row Selection article to see an example]({%slug grid-selection-row%}#selecteditemschanged-event). + ## SelectedCellsChanged Fires when [cell selection is enabled]({%slug grid-selection-overview%}#enable-row-or-cell-selection) and the user selects or deselects one cell or multiple cells, depending on the [selection mode]({%slug grid-selection-overview%}#use-single-or-multiple-selection). +Visit the [Grid Cell Selection article to see an example]({%slug grid-selection-cell%}#selectedcellschanged-event). + ## See Also * [Grid Overview]({%slug grid-overview%}) diff --git a/components/grid/selection/cells.md b/components/grid/selection/cells.md index 6ce322789d..dad9261b4c 100644 --- a/components/grid/selection/cells.md +++ b/components/grid/selection/cells.md @@ -1,7 +1,7 @@ --- title: Cell Selection page_title: Grid - Cells Selection -description: Learn how to select cell in Blazor Grid component. Explore the selected cells. Discover cell selection bevahior when combined with other Grid features. Try the practical sample code for cell selection. +description: Learn how to select cell in Blazor Grid component. Explore the selected cells. Discover cell selection bevahior when combined with other Grid features. Try the practical sample code for cell selection. slug: grid-selection-cell tags: telerik,blazor,grid,selection,cells position: 5 @@ -190,7 +190,7 @@ The `GridSelectedCellDescriptor` type exposes the following properties: When the Grid `Data` collection changes, the `SelectedCells` collection has the following behavior: -* When the user updates a selected cell and the item instance is replaced, you have to also replace the `SelectedCellDescriptor.DataItem` object in the `SelectedCells` collection. Do that in the [Grid `OnUpdate` event]({%slug components/grid/editing/overview%}#events). +* When the user updates a selected cell and the item instance is replaced, you have to also replace the `DataItem` object in the `SelectedCells` collection. Do that in the [Grid `OnUpdate` event]({%slug components/grid/editing/overview%}#events). * When the user deletes a row with selected cells, update the `SelectedCells` collection in the the Grid `OnDelete` event handler. * To select cells from a new item in the Grid you can use the [`OnCreate` event]({%slug components/grid/editing/overview%}#events) to update the `SelectedCells` collection. diff --git a/components/grid/selection/overview.md b/components/grid/selection/overview.md index bb27ae45b0..ca2d6ababd 100644 --- a/components/grid/selection/overview.md +++ b/components/grid/selection/overview.md @@ -27,9 +27,9 @@ You can configure the Grid either for row or cell selection: * Add a `` tag to the `` tag, and set the `SelectionType` parameter to `GridSelectionType.Row`. * Optionally, you can also select rows through the [checkbox column]({%slug components/grid/columns/checkbox%}). * To enable cell selection: - * Add a `` tag to the `` tag, and set the `SelectionType` parameter to the `Cell` member of the `Telerik.Blazor.GridSelectionType` enum. + * Add a `` tag to the `` tag, and set the `SelectionType` parameter to `GridSelectionType.Cell`. -See [Rows Selection Options]({%slug grid-selection-row%}#basics) and [Cells Selection Options]({%slug grid-selection-cell%}#basics) for more details. +See [Rows Selection Basics]({%slug grid-selection-row%}#basics) and [Cells Selection Basics]({%slug grid-selection-cell%}#basics) for more details. ## Use Single or Multiple Selection @@ -48,14 +48,14 @@ The Grid exposes two parameters to get or set its selected rows and cells. Both parameters support two-way binding. You can also use the parameters to pre-select rows or cells for your users. -See [Selected Rows]({%slug grid-selection-row%}#selected-rows) and [Selected Cells]({%slug grid-selection-cell%}#selected-cells) for more details. +See [Rows Selection Basics]({%slug grid-selection-row%}#basics) and [Cells Selection Basics]({%slug grid-selection-cell%}#basics) for more details. ## Events You can respond to the user action of selecting a new item through the Grid events: -* Use the [`SelectedItemsChanged` event]({%slug grid-selection-row%}#selecteditemschanged) to respond to row selection. -* Use the [`SelectedCellsChanged` event]({%slug grid-selection-cell%}#selectedcellschanged) to respond to cell selection. +* Use the [`SelectedItemsChanged` event]({%slug grid-selection-row%}#selecteditemschanged-event) to respond to row selection. +* Use the [`SelectedCellsChanged` event]({%slug grid-selection-cell%}#selectedcellschanged-event) to respond to cell selection. ## Integration with Other Grid Features diff --git a/components/grid/selection/rows.md b/components/grid/selection/rows.md index 9475da1328..d47b232e46 100644 --- a/components/grid/selection/rows.md +++ b/components/grid/selection/rows.md @@ -81,6 +81,8 @@ You can respond to user selection actions through the `SelectedItemsChanged` eve >caption Using the Grid SelectedItemsChanged event ````CSHTML +@* Select rows and handle the SelectedItemsChanged event *@ + (`true`) | Determines if the column header renders a checkbox to select all rows. Set this to `false` if the [TreeList `SelectionMode` is `Single`]({%slug treelist-selection-single%}). The `SelectAll` parameter has no effect when the checkbox column has a [`HeaderTemplate`](#headertemplate). | +| `SelectAll` | `bool`
(`true`) | Determines if the column header renders a checkbox to select all rows. Set this to `false` if the [TreeList `SelectionMode` is `Single`]({%slug treelist-selection-overview%}#use-single-or-multiple-selection). The `SelectAll` parameter has no effect when the checkbox column has a [`HeaderTemplate`](#headertemplate). | | `SelectAllMode` | `TreeListSelectAllMode` enum
(`Current`) | Determines if the header cell checkbox selects all rows on the current page, or all rows in the TreeList. `Current` selects the visible rows on the current page. It does not select the children of collapsed items - they are not part of the [current page]({%slug treelist-paging%}) data. `All` selects all the data items, including ones that may be currently filtered out. | | `SelectChildren` | `bool` | Determines if a parent row checkbox affects the selected state of respective child rows. | diff --git a/components/treelist/events.md b/components/treelist/events.md index ef31550b78..09cd2ef62c 100644 --- a/components/treelist/events.md +++ b/components/treelist/events.md @@ -28,6 +28,7 @@ You can read more about the CUD events in the [Editing Overview]({%slug treelist * [OnExpand and OnCollapse](#onexpand-and-oncollapse) * [Command Button Click](#command-button-click) * [SelectedItemsChanged](#selecteditemschanged) +* [SelectedCellsChanged](#selectedcellschanged) * [OnModelInit](#onmodelinit) * [OnRowClick](#onrowclick) * [OnRowDoubleClick](#onrowdoubleclick) @@ -168,7 +169,15 @@ The command buttons of a treelist provide an `OnClick` event before firing their ## SelectedItemsChanged -Fires when the item selection is enabled and the user changes the selected [item]({%slug treelist-selection-single%}#selecteditemschanged-event) or [items]({%slug treelist-selection-multiple%}#selecteditemschanged-event). +Fires when [row selection is enabled]({%slug treelist-selection-overview%}#enable-row-or-cell-selection) and the user selects or deselects one or multiple rows, depending on the [selection mode]({%slug treelist-selection-overview%}#use-single-or-multiple-selection). + +Visit the [TreeList Row Selection article to see an example]({%slug treelist-selection-row%}#selecteditemschanged-event). + +## SelectedCellsChanged + +Fires when [cell selection is enabled]({%slug treelist-selection-overview%}#enable-row-or-cell-selection) and the user selects or deselects one cell or multiple cells, depending on the [selection mode]({%slug treelist-selection-overview%}#use-single-or-multiple-selection). + +Visit the [TreeList Cell Selection article to see an example]({%slug treelist-selection-cell%}#selectedcellschanged-event). ## OnModelInit diff --git a/components/treelist/selection/cells.md b/components/treelist/selection/cells.md new file mode 100644 index 0000000000..3779bbe3b7 --- /dev/null +++ b/components/treelist/selection/cells.md @@ -0,0 +1,253 @@ +--- +title: Cell Selection +page_title: TreeList - Cells Selection +description: Learn how to select cell in Blazor TreeList component. Explore the selected cells. Discover cell selection bevahior when combined with other TreeList features. Try the practical sample code for cell selection. +slug: treelist-selection-cell +tags: telerik,blazor,treelist,selection,cells +position: 5 +--- + +# Cell Selection + +The TreeList component supports [single or multiple cell selection]({%slug treelist-selection-overview%}#use-single-or-multiple-selection). You can select a cell with mouse click anywhere in the cell. You can access the collection of selected cells, use this collection and manipulate it. You can subscribe to selection events. + +## Basics + +To select a cell, click anywhere in it. + +To select a range of cells in one or more columns, hold the **Shift** key, while clicking on the first and last cell of the range. To select or deselect multiple cells that don't belong to a range, hold the **Ctrl** key. + +You can also select a cell range by holding and dragging the mouse cursor. The dragging motion defines the diagonal of a rectangle and the TreeList will select the cells under this rectangle. To allow this kind of cell selection, set the `DragToSelect` parameter in [`TreeListSelectionSettings`]({%slug treelist-selection-overview%}#enable-row-or-cell-selection). The **Shift** and **Ctrl** modifiers are not supported in drag-to-select mode. + +To enable cell selection: + +1. Set the TreeList `SelectedCells` parameter to a collection of type `IEnumerable`. The collection must be initialized in advance. See [`TreeListSelectedCellDescriptor`](#treelistselectedcelldescriptor) for infomation about the object properties. +1. Add a `` tag to the `` tag, and set the `SelectionType` parameter to the `TreeListSelectionType.Cell`. + +>caption TreeList multiple cell selection + +````CSHTML + + + + + + + + + + + +

Selected Cells:

+ +
    + @foreach (TreeListSelectedCellDescriptor cellDescriptor in SelectedCells) + { +
  • + Column Field: @cellDescriptor.ColumnField, + EmployeeId: @(((Employee)cellDescriptor.DataItem).Id) +
  • + } +
+ +@code { + private List TreeListData { get; set; } = new(); + + private IEnumerable SelectedCells { get; set; } = Enumerable.Empty(); + + protected override void OnInitialized() + { + for (int i = 1; i <= 9; i++) + { + TreeListData.Add(new Employee() + { + Id = i, + ParentId = i <= 3 ? null : i % 3 + 1, + FirstName = "First " + i, + LastName = "Last " + i, + Position = i <= 3 ? "Team Lead" : "Software Engineer" + }); + } + + SelectedCells = new List() { + new TreeListSelectedCellDescriptor() + { + DataItem = TreeListData.ElementAt(2), + ColumnField = nameof(Employee.FirstName) + } + }; + } + + public class Employee + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Position { get; set; } = string.Empty; + } +} +```` + +## SelectedCellsChanged Event + +You can respond to user selection actions through the `SelectedCellsChanged` event. The event handler receives a collection of type `IEnumerable`. The collection may have multiple, single, or no objects in it, depending on the `SelectionMode` and the last user selection. + +>caption Using the TreeList SelectedCellsChanged event + +````CSHTML +@* Select cells and handle the SelectedCellsChanged event *@ + + + + + + + + + + + + +

SelectedItemsChanged fired at: @SelectedCellsChangedLog

+ +

Selected Cells:

+ +
    + @foreach (TreeListSelectedCellDescriptor cellDescriptor in SelectedCells) + { +
  • + Column Field: @cellDescriptor.ColumnField, + EmployeeId: @(((Employee)cellDescriptor.DataItem).Id) +
  • + } +
+ +@code { + private List TreeListData { get; set; } = new(); + + private IEnumerable SelectedCells { get; set; } = Enumerable.Empty(); + + private string SelectedCellsChangedLog { get; set; } = string.Empty; + + protected void OnCellSelect(IEnumerable cellDescriptors) + { + // Update the SelectedCells collection manually. + // When using two-way binding, this happens automatically. + SelectedCells = cellDescriptors; + + SelectedCellsChangedLog = DateTime.Now.ToLongTimeString(); + } + + protected override void OnInitialized() + { + for (int i = 1; i <= 15; i++) + { + TreeListData.Add(new Employee() + { + Id = i, + ParentId = i <= 3 ? null : i % 3 + 1, + FirstName = "First " + i, + LastName = "Last " + i, + Position = i <= 3 ? "Team Lead" : "Software Engineer" + }); + } + + SelectedCells = new List() { + new TreeListSelectedCellDescriptor() + { + DataItem = TreeListData.ElementAt(2), + ColumnField = nameof(Employee.FirstName) + } + }; + } + + public class Employee + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Position { get; set; } = string.Empty; + } +} +```` + +### SelectedCellsChanged and Asynchronous Operations + +The `SelectedCellsChanged` event handler cannot be awaited. To execute asynchronous operations when the user selects rows, use the [`OnRowClick`]({%slug treelist-events%}#onrowclick) or [`OnRowDoubleClick`]({%slug treelist-events%}#onrowdoubleclick) event instead. + +## TreeListSelectedCellDescriptor + +The `TreeListSelectedCellDescriptor` type exposes the following properties: + +@[template](/_contentTemplates/common/parameters-table-styles.md#table-layout) + +| Property Name | Type | Description | +| --- | --- | --- | +| `ColumnField` | `string` | The value of the TreeList column `Field` parameter, if set. | +| `ColumnId` | `string` | The value of the TreeList column `Id` parameter, if set. | +| `DataItem` | `object` | The TreeList data item instance. Cast it to the actual TreeList model type before use. | + +## Selection When Data Changes + +When the TreeList `Data` collection changes, the `SelectedCells` collection has the following behavior: + +* When the user updates a selected cell and the item instance is replaced, you have to also replace the `DataItem` object in the `SelectedCells` collection. Do that in the [TreeList `OnUpdate` event]({%slug treelist-editing-overview%}#events). +* When the user deletes a row with selected cells, update the `SelectedCells` collection in the the TreeList `OnDelete` event handler. +* To select cells from a new item in the TreeList you can use the [`OnCreate` event]({%slug treelist-editing-overview%}#events) to update the `SelectedCells` collection. + +### Equals Comparison + +The items in `SelectedCells` are compared against the items in the TreeList data in order to determine which cells will be highlighted. The default framework behavior is to compare objects by reference. The data item references may not match when: + +* The `SelectedCells` are obtained from a different data source than the all TreeList items, for example, from a separate service. + +In such cases, the selected cells may not appear as expected. You have to [override the `Equals` method of the TreeList model class]({%slug treelist-state%}#basics) so that the items are compared by a unique identifier rather than by reference. When you override `Equals`, it is also recommended to override the [`GetHashCode`](https://docs.microsoft.com/en-us/dotnet/api/system.object.gethashcode) method. + +## Cell Selection and Other TreeList Features + +The selection feature behavior may vary when the TreeList configuration combines cell selection and other TreeList features, such as editing, virtualization, paging, templates. In such cases you need to consider certain limitation or include some modications. + +### Selection and Editing Modes + +When you want to edit a TreeList item, the cell selection has the following behavior: + +* Cell selection is not supported with [`Incell` edit mode]({%slug treelist-editing-incell%}) due to the overlapping pointer events that trigger selection and editing. If both features are enabled, only the editing will work. +* [`Inline` edit mode]({%slug treelist-editing-inline%}) and [`Popup` edit mode]({%slug treelist-editing-popup%}) integrate with cell selection without limitations. + +### Selection and Virtual Scrolling + +When the TreeList has [virtual scrolling]({%slug treelist-virtual-scrolling%}), the component is able to select a range of cells with **Shift** only if all rows in that range are currently rendered. Consider the following scenario: + +1. Select a cell. +1. Scroll down, so that virtualization kicks in and the rendered rows are no longer the same. +1. Select another cell with **Shift**. + +In this case, the range selection will start from the first row that is currently rendered. Compare with [Selection and paging](#selection-and-paging) below. + +### Selection and Paging + +The `SelectedCells` collection persists across paging. + +### Selection and Templates + +When using [TreeList templates]({%slug treelist-templates-overview%}) with cell selection: + +* If you are using a [TreeList column template]({%slug treelist-templates-column%}) and you have a clickable element in the template, wrap this element in a container with a `@onclick:stopPropagation` directive. You can check the knowledge base article on [how to prevent row selection when the user clicks another component in the Grid column template]({%slug grid-kb-row-selection-in-column-template%}). It is for the Grid component, but the concept is identical and it applies for both row and cell selection. +* If you are using a [row template]({%slug treelist-templates-row%}) the TreeList does not support cell selection. The row template removes the built-in cell instances and the HTML markup may not even include the expected number of cells. + +## See Also + +* [Live Demo: TreeList Cell Selection](https://demos.telerik.com/blazor-ui/treelist/cell-selection) diff --git a/components/treelist/selection/multiple.md b/components/treelist/selection/multiple.md deleted file mode 100644 index badc4fe00e..0000000000 --- a/components/treelist/selection/multiple.md +++ /dev/null @@ -1,409 +0,0 @@ ---- -title: Multiple Rows -page_title: TreeList - Multiple Selection -description: Single row selection in the treelist for Blazor. -slug: treelist-selection-multiple -tags: telerik,blazor,treelist,selection,multiple -published: True -position: 2 ---- - -# Multiple Row Selection - -The treelist component can allow the user to select many rows at a time, or to select [only one]({%slug treelist-selection-single %}). - -In this article: - -* [Basics](#basics) -* [Checkbox Selection](#checkbox-selection) -* [Selected Items](#selected-items) -* [Examples](#examples) - * [Multiple Row Selection and Checkbox](#multiple-row-selection-and-checkbox) - * [SelectedItemsChanged Event](#selecteditemschanged-event) - * [Two-way Binding of SelectedItems](#two-way-binding-of-selecteditems) - - -## Basics - -To use **multiple** row selection, set the `SelectionMode` property to `Telerik.Blazor.TreeListSelectionMode.Multiple`. - -In Multiple SelectionMode, selection could be made using the following approaches: - -* Click on a row to select only that row (and deselect any others) -* Press and hold `Ctrl` and click the desired rows to select or deselect them. -* Click on the starting row of a range of rows you want selected, press and hold `Shift`, and click on the last row of the range. The last selected item is the start point of the range and the current target row is the end of the selection. -* Select the checkbox of each desired row. - ->tip The [Examples](#examples) section showcases how you can use the treelist features together. - -## Checkbox Selection - -To add checkboxes in each row that the user can use for selection, add a [`TreeListCheckboxColumn`]({%slug treelist-columns-checkbox%}) in the `TreeListColumns` collection of the treelist. The column provides [additional configuration settings related to selection]({%slug treelist-columns-checkbox%}#parameters). - -**Usage:** - -````CSHTML - - -```` - -## Selected Items - -The `SelectedItemsChanged` event receives a collection of the treelist data model. It may have no items in it. - -You can use the `SelectedItems` collection in two-way binding. You can use this to pre-select rows for your users. - -The `SelectedItems` collection persists across paging operations. Changing the page will keep it populated and you can add more items to the selection. - -## Examples - -### Multiple Row Selection and Checkbox - -You can add a checkbox column for selection. It is required if the `InCell` edit mode is used. Otherwise, it is optional. - ->caption Multiple Selection and a checkbox column. - -````CSHTML -You can select items by clicking a checkbox, or by clicking the rows. The Ctrl and Shift keys let you select more than one row when clicking it. -
-In this example, there is only visual indication of the selection, see the next examples for using the selection data. - - - - - - - - - - - - - -@code { - public List Data { get; set; } - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation and retrieval for CUD operations on the current view-model data - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -### SelectedItemsChanged Event - -You can respond to the user action of selecting a new item through the `SelectedItemsChanged` event. - ->caption Multiple Selection and handling the SelectedItemsChanged event - -````CSHTML -@*Show details for selected items via the selection changed event*@ - - - - - - - - - - - -@if (SelectedItems.Any()) -{ -

Send email to:

-
    - @foreach (Employee item in SelectedItems) - { -
  • @item.EmailAddress
  • - } -
-} - -@code { - public List Data { get; set; } - public IEnumerable SelectedItems { get; set; } = Enumerable.Empty(); - - protected void OnSelect(IEnumerable employees) - { - SelectedItems = employees; - } - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation and retrieval for CUD operations on the current view-model data - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - - // pre-select some items. Note that this will not automatically select their children - // regardless of the SelectChildren parameter of the select column - SelectedItems = Data[0].DirectReports.Take(2).ToList(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -@[template](/_contentTemplates/common/issues-and-warnings.md#valuechanged-lambda-required) - -### Two-way Binding of SelectedItems - -You can predefine the selected items for your users through the two-way binding of the `SelectedItems` property. The collection will be updated by the treelist when the selection changes. Note that both binding to the property and using its event cannot be used at the same time, as Blazor only allows one. - ->caption Multiple Selection and two-way binding of the `SelectedItems` property - -````CSHTML -@*Use the selected items collection*@ - - - - - - - - - - - -@if (SelectedItems.Any()) -{ -

Send email to:

-
    - @foreach (Employee item in SelectedItems) - { -
  • @item.EmailAddress
  • - } -
-} - -@code { - public List Data { get; set; } - public IEnumerable SelectedItems { get; set; } = Enumerable.Empty(); - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation and retrieval for CUD operations on the current view-model data - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - - // preselect some items. Note that this will not automatically select their children - // regardless of the SelectChildren parameter of the select column - SelectedItems = Data[0].DirectReports.Take(2).ToList(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - - -## See Also - - * [Live Demo: TreeList Selection](https://demos.telerik.com/blazor-ui/treelist/selection) - * [Live Demo: TreeList Checkbox Selection](https://demos.telerik.com/blazor-ui/treelist/checkbox-only-selection) - * [Single Selection]({%slug treelist-selection-single%}) - diff --git a/components/treelist/selection/overview.md b/components/treelist/selection/overview.md index 9a85760952..73f74157bd 100644 --- a/components/treelist/selection/overview.md +++ b/components/treelist/selection/overview.md @@ -1,300 +1,69 @@ --- title: Overview page_title: TreeList - Selection Overview -description: Selection basics in the treelist for Blazor. +description: Selection basics in the TreeList for Blazor. slug: treelist-selection-overview -tags: telerik,blazor,treelist,selection,overview +tags: telerik,blazor,treelist,selection,overview published: True position: 0 --- # TreeList Selection -The treelist component offers support for row selection. +The TreeList component supports row and cell selection. When you select a row or a cell, they will be highlighted in the TreeList. This article provides an overview of the TreeList selection behavior and configuration: -In this article: +* [Enable row or cell selection](#enable-row-or-cell-selection) +* [Use single or multiple selection](#use-single-or-multiple-selection) +* [Access selected rows or cells](#access-selected-rows-or-cells) +* [Handle selection events](#events) +* [Combine selection with other TreeList features](#integration-with-other-treelist-features) -* [Selection Basics](#selection-basics) - * [Example - Enable Row Selection](#example---enable-row-selection-multiple) - * [Example - Select rows with checkboxes only](#example---select-rows-with-checkboxes-only) -* [Notes](#notes) - * [Editing Modes](#editing-modes) - * [Selection in Template](#selection-in-template) - * [Asynchronous Operations](#asynchronous-operations) - * [Handle Data Changes](#handle-data-changes) +## Enable Row or Cell Selection +You can configure the TreeList either for row or cell selection: +* To enable row selection: + * Set the [TreeList `SelectionMode` parameter](#use-single-or-multiple-selection) or + * Add a `` tag to the `` tag, and set the `SelectionType` parameter to `TreeListSelectionType.Row`. + * Optionally, you can also select rows through the [checkbox column]({%slug treelist-columns-checkbox%}). +* To enable cell selection: + * Add a `` tag to the `` tag, and set the `SelectionType` parameter to `TreeListSelectionType.Cell`. -## Selection Basics +See [Row Selection Basics]({%slug treelist-selection-row%}#basics) and [Cell Selection Basics]({%slug treelist-selection-cell%}#basics) for more details. -You can configure the selection behavior by setting `SelectionMode` to a member of the `Telerik.Blazor.TreeListSelectionMode` enum. The row selection can be: +## Use Single or Multiple Selection -* `None` - (the default value) to disable row selection -* [Single]({%slug treelist-selection-single%}) -* [Multiple]({%slug treelist-selection-multiple%}) +You can configure the selection behavior by setting the TreeList `SelectionMode` parameter to a member of the `Telerik.Blazor.TreeListSelectionMode` enum. The TreeList supports the following selection modes: -To select a row, click on it. To select multiple rows, hold down the `Ctrl` or `Shift` key to extend the selection. +* `None` (default)—Disables row and cell selection. +* `Single`—Allows the user to select only one cell or row at a time. If the user attempts to select multiple cells or rows sequentially, only the most recent selection will take effect. +* `Multiple`—Allows the user to select multiple rows or cells at a time. -You can also use a checkbox column to select rows. To use it, add a [`TreeListCheckboxColumn`]({%slug treelist-columns-checkbox%}) in the `TreeListColumns` collection of the treelist. It works with both selection modes. With multiple selection mode, the checkbox column offers [additional functionality]({%slug treelist-selection-multiple%}#checkbox-selection). +## Access Selected Rows or Cells -You can get or set the selected items through the `SelectedItems` property. It is a collection of items from the treelist's `Data`. +The TreeList exposes two parameters to get or set its selected rows and cells. -The [single selection]({%slug treelist-selection-single%}) and [multiple selection]({%slug treelist-selection-multiple%}) articles provide more examples and details on using the treelist features. +* Use the `SelectedItems` parameter (`IEnumerable`) to access the selected rows. +* Use the `SelectedCells` parameter (`IEnumerable`) to access the selected cells. -### Example - Enable Row Selection (multiple) +Both parameters support two-way binding. You can also use the parameters to pre-select rows or cells for your users. -````CSHTML -@* See how to enable selection and use the SelectedItems the TreeList provides *@ +See [Row Selection Basics]({%slug treelist-selection-row%}#basics) and [Cell Selection Basics]({%slug treelist-selection-cell%}#basics) for more details. - - - - - - - - - +* Use the [`SelectedItemsChanged` event]({%slug treelist-selection-row%}#selecteditemschanged-event) to respond to row selection. +* Use the [`SelectedCellsChanged` event]({%slug treelist-selection-cell%}#selectedcellschanged-event) to respond to cell selection. -@if (SelectedItems.Any()) -{ -
    - @foreach (Employee item in SelectedItems) - { -
  • @item.Id
  • - } -
-} - -@code { - public List Data { get; set; } - public IEnumerable SelectedItems { get; set; } = Enumerable.Empty(); - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation and retrieval for CUD operations on the current view-model data - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -### Example - Select rows with checkboxes only - -````CSHTML -@* Require clicks on the checkboxes for row selection*@ - - - - - - - - - - - -@code { - public List Data { get; set; } - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation and retrieval for CUD operations on the current view-model data - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -## Notes - -### Editing Modes - -#### InCell Edit Mode - -In the [Incell EditMode]({%slug treelist-editing-incell%}) selection can be applied only via a [checkbox column]({%slug treelist-columns-checkbox%}) (``). This is required due to the overlapping action that triggers selection and InCell editing (clicking in the row) - if row click selection was enabled with InCell editing, each attempt to select a row would put a cell in edit mode; and each attempt to edit a cell would select a new row. Such user experience is confusing, and so selection will only work through the row selection checkbox. - -To see how to select the row that is being edited in InCell edit mode without using a `` check out the [Grid Row Selection in Edit with InCell EditMode]({%slug grid-kb-row-select-incell-edit%}) Knowledge Base article - it is for the Grid component, but the concept is the same. - -#### Inline and Popup Edit Modes - -In [Inline EditMode]({%slug treelist-editing-inline%}) and [Popup EditMode]({%slug treelist-editing-popup%}) selection can be done by clicking on the desired row or by using a `< TreeListCheckboxColumn />`. - -### Selection in Template - -When using the treelist [Template]({%slug treelist-templates-overview%}) and you want to stop the Selection from being triggered when the user clicks in it, you should add the `@onclick:stopPropagation` directive to the element. - ->caption Prevent row selection from happening when the user clicks inside a template - -````CSHTML - - - -```` - -If you are using the [Row Template]({%slug treelist-templates-row%}), the treelist cannot render selection checkboxes for you, so you have to bind them yourself to a field in the model, and handle their selection changed event to populate the `SelectedItems` collection of the treelist. You can find an example to get started in the following thread (it is for the grid, but the concept is identical): [Grid Row Template with Selection - Unsure how to Bind to Selected Item](https://feedback.telerik.com/blazor/1463819-treelist-row-template-with-selection-unsure-how-to-bind-to-selected-item) - -### Asynchronous Operations - -Asynchronous operations such as loading data on demand should be handled in the [`OnExpand`]({%slug treelist-data-binding-load-on-demand%}), [`OnRowClick`]({%slug treelist-events%}#onrowclick) or [`OnRowDoubleClick`]({%slug treelist-events%}#onrowdoubleclick) events, rather than in the [`SelectedItemsChanged`]({%slug treelist-events%}#selecteditemschanged) event. - -### Handle Data Changes - -When the treelist `Data` collection changes, the `SelectedItems` collection has the following behavior: - -* If the treelist does *not* use an `ObservableCollection` for its `Data` - The `SelectedItems` collection will be preserved. You need to clear or manipulate it when the data is changed according to your needs and business logic. - - * If you update or delete an item, you must make the same update in the selected items through the treelist [editing events]({%slug treelist-editing-overview%}). - -* When using an `ObservableCollection` for the treelist `Data`- If an item is removed or the entire data is cleared using the collection's `.Clear()` method, it will automatically update the `SelectedItems` collection too (the removed Data items will be removed from the Selected Items collection). - - * The other CRUD operations (Create and Update), you should use the treelist [editing events]({%slug treelist-editing-overview%}) to handle the situation according to your business logic and preferred behavior. - * When the data changes and the selected items are cleared, the `SelectedItemsChanged` event will fire with the empty collection. If you are using two-way binding, the collection will be cleared. +## Integration with Other TreeList Features +The selection feature behavior may differ when the TreeList configuration includes row or cell selection and other TreeList features. In these situations, certain limitations might arise, or additional adjustments may be required. +See [Rows Selection and Other TreeList Features]({%slug treelist-selection-row%}#row-selection-and-other-treelist-features) and [Cells Selection and Other TreeList Features]({%slug treelist-selection-cell%}#cell-selection-and-other-treelist-features) for more details. ## See Also -* [Live Demo: TreeList Selection](https://demos.telerik.com/blazor-ui/treelist/selection) -* [Live Demo: TreeList Checkbox Selection](https://demos.telerik.com/blazor-ui/treelist/checkbox-only-selection) -* [Single Selection]({%slug treelist-selection-single%}) -* [Multiple Selection]({%slug treelist-selection-multiple%}) +* [Live Demo: TreeList Row Selection](https://demos.telerik.com/blazor-ui/treelist/row-selection) +* [Live Demo: TreeList Cell Selection](https://demos.telerik.com/blazor-ui/treelist/cell-selection) \ No newline at end of file diff --git a/components/treelist/selection/rows.md b/components/treelist/selection/rows.md new file mode 100644 index 0000000000..0d5875da3e --- /dev/null +++ b/components/treelist/selection/rows.md @@ -0,0 +1,220 @@ +--- +title: Row Selection +page_title: TreeList - Rows Selection +description: Learn how to select row in Blazor TreeList component. Explore the selected rows. Discover row selection bevahior when combined with other TreeList features. Try the practical sample code for row selection. +slug: treelist-selection-row +tags: telerik,blazor,treelist,selection,rows +previous_url: /treelist-selection-multiple,/treelist-selection-single +position: 3 +--- + +# Row Selection + +The TreeList component supports [single or multiple row selection]({%slug treelist-selection-overview%}#use-single-or-multiple-selection). You can select a row with mouse click and through a checkbox column. You can access the collection of selected rows, use this collection and modify it. You can subscribe to selection events. + +## Basics + +By default, users can select rows by clicking anywhere in the row, except on command buttons. + +To select a range of rows, hold the **Shift** key, while clicking on the first and last row of the range. To select or deselect multiple rows that don't belong to a range, hold the **Ctrl** key. + +Check the [TreeList Keyboard navigation demo](https://demos.telerik.com/blazor-ui/treelist/keyboard-navigation) for detailed information about selecting rows with the keyboard. + +You can also render a checkbox column that allows users to select and deselect rows. To use checkbox selection, add a [`TreeListCheckboxColumn`]({%slug treelist-columns-checkbox%}) in the `TreeListColumns` collection of the TreeList. The `TreeListCheckboxColumn` provides [additional configuration settings related to selection]({%slug treelist-columns-checkbox%}#parameters). + +>caption TreeList multiple row selection + +````CSHTML +< + + + + + + + +

Selected Employees:

+ +
    + @foreach (Employee employee in SelectedEmployees) + { +
  • @employee.FirstName
  • + } +
+ +@code { + private List TreeListData { get; set; } = new(); + private IEnumerable SelectedEmployees { get; set; } = Enumerable.Empty(); + + protected override void OnInitialized() + { + TreeListData = new List(); + + for (int i = 1; i <= 9; i++) + { + TreeListData.Add(new Employee() + { + Id = i, + ParentId = i <= 3 ? null : i % 3 + 1, + FirstName = "First " + i, + LastName = "Last " + i, + Position = i <= 3 ? "Team Lead" : "Software Engineer" + }); + } + + SelectedEmployees = new List() { TreeListData.ElementAt(2) }; + } + + public class Employee + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Position { get; set; } = string.Empty; + } +} +```` + +## SelectedItemsChanged Event + +You can respond to user selection actions through the `SelectedItemsChanged` event. The event handler receives a collection of the TreeList data model. The collection may have multiple, single, or no items in it, depending on the `SelectionMode` and the last user selection. + +>caption Using the TreeList SelectedItemsChanged event + +````CSHTML +@* Select rows and handle the SelectedItemsChanged event *@ + + + + + + + + + +

SelectedItemsChanged fired at: @SelectedItemsChangedLog

+ +

Selected Employees:

+ +
    + @foreach (Employee employee in SelectedEmployees) + { +
  • @employee.FirstName
  • + } +
+ +@code { + private List TreeListData { get; set; } = new(); + + private IEnumerable SelectedEmployees { get; set; } = Enumerable.Empty(); + + private string SelectedItemsChangedLog { get; set; } = string.Empty; + + protected void OnRowSelect(IEnumerable employees) + { + // Update the SelectedItems collection manually. + // When using two-way binding, this happens automatically. + SelectedEmployees = employees; + + SelectedItemsChangedLog = DateTime.Now.ToLongTimeString(); + } + + protected override void OnInitialized() + { + for (int i = 1; i <= 9; i++) + { + TreeListData.Add(new Employee() + { + Id = i, + ParentId = i <= 3 ? null : i % 3 + 1, + FirstName = "First " + i, + LastName = "Last " + i, + Position = i <= 3 ? "Team Lead" : "Software Engineer" + }); + } + + SelectedEmployees = new List() { TreeListData.ElementAt(2) }; + } + + public class Employee + { + public int Id { get; set; } + public int? ParentId { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Position { get; set; } = string.Empty; + } +} +```` + +### SelectedItemsChanged and Asynchronous Operations + +The `SelectedItemsChanged` event handler cannot be awaited. To execute asynchronous operations when the user selects rows, use the [`OnRowClick`]({%slug treelist-events%}#onrowclick) or [`OnRowDoubleClick`]({%slug treelist-events%}#onrowdoubleclick) event instead. + +## Selection When Data Changes + +When the TreeList `Data` collection changes, the `SelectedItems` collection has the following behavior: + +* When the user updates a selected item and the item instance is replaced, you have to also replace the selected item object in the `SelectedItems` collection. Do that in the [TreeList `OnUpdate` event]({%slug treelist-editing-overview%}#events). +* When the user deletes a selected item, the TreeList automatically deletes it from the `SelectedItems` collection and the [`SelectedItemsChanged` event](#selecteditemschanged) fires. +* To select a new item in the TreeList you can use the [`OnCreate` event]({%slug treelist-editing-overview%}#events) to update the `SelectedItems` collection. + +## Equals Comparison + +The items in `SelectedItems` are compared against the items in the TreeList data in order to determine which rows will be highlighted. The default framework behavior is to compare objects by reference. The data item references may not match when: + +* The `SelectedItems` are obtained from a different data source than the all TreeList items, for example, from a separate service. + +In such cases, the selected rows may not appear as expected. You have to [override the `Equals` method of the TreeList model class]({%slug treelist-state%}#basics) so that the items are compared by a unique identifier rather than by reference. When you override `Equals`, it is also recommended to override the [`GetHashCode`](https://docs.microsoft.com/en-us/dotnet/api/system.object.gethashcode) method. + +## Row Selection and Other TreeList Features + +The selection behavior may vary when other TreeList features are enabled, such as editing, virtualization, paging, column and row templates, row drag and drop. In such cases you need to consider certain limitations or adjust the application code. + +### Selection and Editing Modes + +When users edit rows, the row selection has the following behavior: + +* In [`Incell` edit mode]({%slug treelist-editing-incell%}) the row selection can work only through a [checkbox column]({%slug treelist-columns-checkbox%}). This is required due to the overlapping pointer events that trigger selection and editing. To see how to select the row that is being edited in `InCell` edit mode without using a `` check out the [Row Selection in Edit with InCell EditMode]({%slug grid-kb-row-select-incell-edit%}) KB article. It is for the Grid component, but the concept is the same. +* [`Inline` edit mode]({%slug treelist-editing-inline%}) and [`Popup` edit mode]({%slug treelist-editing-popup%}) integrate with row selection without limitations. + +### Selection and Virtual Scrolling + +When the TreeList has [virtual scrolling]({%slug treelist-virtual-scrolling%}), the component is able to select a range of rows with **Shift** only if all rows in that range are currently rendered. Consider the following scenario: + +1. Select a row. +1. Scroll down, so that virtualization kicks in and the rendered rows are no longer the same. +1. Select another row with **Shift**. + +In this case, the range selection will start from the first row that is currently rendered. Compare with [Selection and paging](#selection-and-paging) below. + +### Selection and Paging + +The `SelectedItems` collection persists across paging. + +### Selection and Templates + +When using [TreeList templates]({%slug treelist-templates-overview%}) with row selection: + +* If you are using a [TreeList column template]({%slug treelist-templates-column%}) and you have a clickable element in the template, you can check the knowledge base article on [how to prevent row selection when the user clicks another component in the Grid column template]({%slug grid-kb-row-selection-in-column-template%}). It is for the Grid component, but the concept is identical. +* If you are using a [row template]({%slug treelist-templates-row%}) the TreeList cannot render a built-in [checkbox column]({%slug treelist-columns-checkbox%}). You have to render checkboxes manually and handle their changed event to populate the `SelectedItems` collection of the TreeList. You can find an example to get started in the following thread: [Grid Row Template with Selection - Unsure how to Bind to Selected Item](https://feedback.telerik.com/blazor/1463819-grid-row-template-with-selection-unsure-how-to-bind-to-selected-item). It is for the Grid component, but the concept is identical. + +### Selection and Row Drag and Drop + +The TreeList clears the `SelectedItems` collection when the user drags and drops selected rows. + +## See Also + +* [Live Demo: TreeList Row Selection](https://demos.telerik.com/blazor-ui/treelist/row-selection) diff --git a/components/treelist/selection/single.md b/components/treelist/selection/single.md deleted file mode 100644 index d05b35c009..0000000000 --- a/components/treelist/selection/single.md +++ /dev/null @@ -1,405 +0,0 @@ ---- -title: Single Row -page_title: TreeList - Single Selection -description: Single row selection in the treelist for Blazor. -slug: treelist-selection-single -tags: telerik,blazor,treelist,selection,single -published: True -position: 1 ---- - -# Single Row Selection - -The treelist component can allow the user to select only a single row at a time, or to select [multiple]({%slug treelist-selection-multiple %}). - -In this article: - - -* [Basics](#basics) -* [Checkbox Selection](#checkbox-selection) -* [Selected Items](#selected-items) -* [Examples](#examples) - * [Single Row Selection and Checkbox](#single-row-selection-and-checkbox) - * [SelectedItemsChanged Event](#selecteditemschanged-event) - * [Two-way Binding of SelectedItems](#two-way-binding-of-selecteditems) - - -## Basics - -To use **single** row selection, set the `SelectionMode` property to `Telerik.Blazor.TreeListSelectionMode.Single`. - -To deselect the item, click its checkbox again, or hold the `Ctrl` key and click/tap the row. - ->tip The [Examples](#examples) section showcases how you can use the treelist features together. - -## Checkbox Selection - -In Single SelectionMode, selection is applied with a click on a row, or by [clicking a checkbox if the `TreeListCheckboxColumn` is present]({%slug treelist-columns-checkbox%}). - -Only one row can be selected at a time, even with checkboxes enabled, so the last one that is clicked will be selected. - -If you add a checkbox column, you should set its `SelectAll` parameter to `false` to disable the header checkbox that will select all rows. - -## Selected Items - -The `SelectedItemsChanged` event receives a collection of the treelist data model that has one member only. - -You can use the `SelectedItems` collection in two-way binding. You can use this to pre-select a row for your users. - -The `SelectedItems` collection persists across paging operations. Changing the page will keep it populated. - -If the collection has more than one item in it, the treelist will use the last item to select the row in single selection mode. - -## Examples - -### Single Row Selection and Checkbox - -You can add a checkbox column for single selection. It is required if the `InCell` edit mode is used. Otherwise, it is optional. - ->caption Single Selection and a checkbox column. - -````CSHTML -@* Single selection can be done by clicking a row or through a checkbox *@ - - - - - - - - - - - - - - -@code { - public List Data { get; set; } - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -### SelectedItemsChanged Event - -You can respond to the user action of selecting a new item through the `SelectedItemsChanged` event. - -The example below shows how to handle the `SelectedItemsChanged` event to extract information about the selected item and use it to populate a second treelist with details about the selected record. - ->caption Single Selection and handling the SelectedItemsChanged event - -````CSHTML -@* Use the selection change event to show detail data *@ - - - - - - - - - - - -@if (SelectedEmployee != null) -{ -

- Send private message to: - @SelectedItems.ToList()[0].Name -

-} - -@code { - public List Data { get; set; } - public IEnumerable SelectedItems { get; set; } = Enumerable.Empty(); - - Employee SelectedEmployee { get; set; } - - protected void OnSelect(IEnumerable employees) - { - SelectedEmployee = employees.FirstOrDefault(); - // update the collection so that the treelist can highlight the correct item - // when two-way binding is used this happens automatically, but the framework does not allow two-way binding and the event at the same time - SelectedItems = new List { SelectedEmployee }; - - // note: an async operation here can break the selection and may not even render its results in the view - } - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - - // preselect an item - SelectedEmployee = Data[0].DirectReports[1]; - SelectedItems = new List { SelectedEmployee }; - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - -@[template](/_contentTemplates/common/issues-and-warnings.md#valuechanged-lambda-required) - -### Two-way Binding of SelectedItems - -You can predefine the selected item for your users through the two-way binding of the `SelectedItems` property. The collection will be updated by the treelist when the selection changes. Note that both binding to the property and using its event cannot be used at the same time, as Blazor only allows one. - ->caption Single Selection and two-way binding of the `SelectedItems` property - -````CSHTML -@*Use the selected items collection*@ - - - - - - - - - - - -@if (SelectedItems.Any()) -{ -

- Send private message to: - @SelectedItems.ToList()[0].Name -

-} - -@code { - public List Data { get; set; } - public IEnumerable SelectedItems { get; set; } = Enumerable.Empty(); - - // sample model - - public class Employee - { - public int Id { get; set; } - public List DirectReports { get; set; } - public string Name { get; set; } - public string EmailAddress { get; set; } - public DateTime HireDate { get; set; } - } - - // data generation - - // used in this example for data generation - public int LastId { get; set; } = 1; - - protected override async Task OnInitializedAsync() - { - Data = await GetTreeListData(); - - // preselect an item - SelectedItems = Data[0].DirectReports.Take(1).ToList(); - } - - async Task> GetTreeListData() - { - List data = new List(); - - for (int i = 1; i < 15; i++) - { - Employee root = new Employee - { - Id = LastId, - Name = $"root: {i}", - EmailAddress = $"{i}@example.com", - HireDate = DateTime.Now.AddYears(-i), - DirectReports = new List(), - }; - data.Add(root); - LastId++; - - for (int j = 1; j < 4; j++) - { - int currId = LastId; - Employee firstLevelChild = new Employee - { - Id = currId, - Name = $"first level child {j} of {i}", - EmailAddress = $"{currId}@example.com", - HireDate = DateTime.Now.AddDays(-currId), - DirectReports = new List(), - }; - root.DirectReports.Add(firstLevelChild); - LastId++; - - for (int k = 1; k < 3; k++) - { - int nestedId = LastId; - firstLevelChild.DirectReports.Add(new Employee - { - Id = LastId, - Name = $"second level child {k} of {j} and {i}", - EmailAddress = $"{nestedId}@example.com", - HireDate = DateTime.Now.AddMinutes(-nestedId) - }); ; - LastId++; - } - } - } - - return await Task.FromResult(data); - } -} -```` - - - -## See Also - - * [Live Demo: TreeList Selection](https://demos.telerik.com/blazor-ui/treelist/selection) - * [Live Demo: TreeList Checkbox Selection](https://demos.telerik.com/blazor-ui/treelist/checkbox-only-selection) - * [Multiple Selection]({%slug treelist-selection-multiple%})