|
| 1 | +--- |
| 2 | +title: TreeView Selection Styles Apply to Full Item Width |
| 3 | +description: |
| 4 | +type: troubleshooting |
| 5 | +page_title: How to Prevent the TreeView Selection and Hover Styles From Applying to the Full Item Width |
| 6 | +meta_title: How to Prevent the TreeView Selection and Hover Styles From Applying to the Full Item Width |
| 7 | +slug: treeview-kb-node-selection-only-on-item-text |
| 8 | +tags: telerik, blazor, treeview, styles |
| 9 | +ticketid: 1716441 |
| 10 | +res_type: kb |
| 11 | +--- |
| 12 | + |
| 13 | +## Environment |
| 14 | + |
| 15 | +<table> |
| 16 | + <tbody> |
| 17 | + <tr> |
| 18 | + <td>Product</td> |
| 19 | + <td>TreeView for Blazor</td> |
| 20 | + </tr> |
| 21 | + <tr> |
| 22 | + <td>Version</td> |
| 23 | + <td>14.0.0 and above</td> |
| 24 | + </tr> |
| 25 | + </tbody> |
| 26 | +</table> |
| 27 | + |
| 28 | +## Description |
| 29 | + |
| 30 | +After upgrading Telerik UI for Blazor to version 14 and above, the focus, hover and selection styles span over the whole TreeView node. In older versions, these styles were applied only to the TreeView item text. This article shows how to restore the legacy component appearance. |
| 31 | + |
| 32 | +## Cause |
| 33 | + |
| 34 | +The change in the TreeView styling aims to improve the UX in the new [DropDownTree component](slug:dropdowntree-overview), which must support focus, hover and selection styles on the whole dropdown width, which means on the whole TreeView width. |
| 35 | + |
| 36 | +## Solution |
| 37 | + |
| 38 | +There are two ways to apply focus, hover, and selection styles on the TreeView item text only: |
| 39 | + |
| 40 | +* [Automatically restrict the TreeView width, based on the node levels and node text length](#restrict-treeview-width). |
| 41 | +* [Override the Telerik CSS theme, remove the selection, hover, and focus styles from their default TreeView element and apply them to a child element](#move-styles-to-child-element). |
| 42 | + |
| 43 | +### Restrict TreeView Width |
| 44 | + |
| 45 | +Set a custom `Class` to the TreeView and use the CSS class to apply a `width: max-content` style. As a result, the TreeView will automatically shrink horizontally, based on the number of node levels and the largest node text length. The approach is simpler, but the focus, hover, and selection styles will start from the left end of the TreeView. |
| 46 | + |
| 47 | +>caption Restrict TreeView width and focus shadow, hover background, and selection background |
| 48 | +
|
| 49 | +````RAZOR |
| 50 | +<TelerikTreeView Data="@FlatData" |
| 51 | + @bind-ExpandedItems="@ExpandedItems" |
| 52 | + Class="treeview-width" |
| 53 | + SelectionMode="@TreeViewSelectionMode.Multiple" |
| 54 | + @bind-SelectedItems="@TreeViewSelectedItems" /> |
| 55 | +
|
| 56 | +<style> |
| 57 | + .treeview-width { |
| 58 | + width: max-content; |
| 59 | + } |
| 60 | +</style> |
| 61 | +
|
| 62 | +@code { |
| 63 | + private IEnumerable<TreeItem> FlatData { get; set; } = new List<TreeItem>(); |
| 64 | + private IEnumerable<object> TreeViewSelectedItems { get; set; } = new List<TreeItem>(); |
| 65 | + private IEnumerable<object> ExpandedItems { get; set; } = new List<TreeItem>(); |
| 66 | +
|
| 67 | + private int TreeLevels { get; set; } = 3; |
| 68 | + private int RootItems { get; set; } = 2; |
| 69 | + private int ItemsPerLevel { get; set; } = 2; |
| 70 | + private int IdCounter { get; set; } = 1; |
| 71 | +
|
| 72 | + protected override void OnInitialized() |
| 73 | + { |
| 74 | + FlatData = LoadFlat(); |
| 75 | +
|
| 76 | + ExpandedItems = FlatData.Where(x => x.HasChildren == true); // && x.ParentId == null |
| 77 | + } |
| 78 | +
|
| 79 | + private List<TreeItem> LoadFlat() |
| 80 | + { |
| 81 | + List<TreeItem> items = new List<TreeItem>(); |
| 82 | +
|
| 83 | + PopulateChildren(items, null, 1); |
| 84 | +
|
| 85 | + return items; |
| 86 | + } |
| 87 | +
|
| 88 | + private void PopulateChildren(List<TreeItem> items, int? parentId, int level) |
| 89 | + { |
| 90 | + var itemCount = level == 1 ? RootItems : ItemsPerLevel; |
| 91 | + for (int i = 1; i <= itemCount; i++) |
| 92 | + { |
| 93 | + var itemId = IdCounter++; |
| 94 | + items.Add(new TreeItem() |
| 95 | + { |
| 96 | + Id = itemId, |
| 97 | + Text = $"Level {level} Item {i}", |
| 98 | + ParentId = parentId, |
| 99 | + HasChildren = level < TreeLevels |
| 100 | + }); |
| 101 | +
|
| 102 | + if (level < TreeLevels) |
| 103 | + { |
| 104 | + PopulateChildren(items, itemId, level + 1); |
| 105 | + } |
| 106 | + } |
| 107 | + } |
| 108 | +
|
| 109 | + public class TreeItem |
| 110 | + { |
| 111 | + public int Id { get; set; } |
| 112 | + public int? ParentId { get; set; } |
| 113 | + public bool HasChildren { get; set; } |
| 114 | + public string Text { get; set; } = string.Empty; |
| 115 | + public object? Icon { get; set; } |
| 116 | +
|
| 117 | + } |
| 118 | +} |
| 119 | +```` |
| 120 | + |
| 121 | +### Move Styles to Child Element |
| 122 | + |
| 123 | +[Override the Telerik CSS theme](slug:themes-override), remove the selection, hover, and focus styles from their default TreeView element and apply them to a child element. This approach is more complex to implement, but achieves the exact same TreeView styling from versions 13.x and before. |
| 124 | + |
| 125 | +>caption Move TreeView focus, hover, and selection styles to a child element |
| 126 | +
|
| 127 | +````RAZOR |
| 128 | +<TelerikTreeView Data="@FlatData" |
| 129 | + @bind-ExpandedItems="@ExpandedItems" |
| 130 | + Class="treeview-selection-width" |
| 131 | + SelectionMode="@TreeViewSelectionMode.Multiple" |
| 132 | + @bind-SelectedItems="@TreeViewSelectedItems" /> |
| 133 | +
|
| 134 | +<style> |
| 135 | + /* Selection */ |
| 136 | + .treeview-selection-width .k-selected { |
| 137 | + color: inherit; |
| 138 | + background-color: transparent; |
| 139 | + } |
| 140 | +
|
| 141 | + .treeview-selection-width .k-selected .k-treeview-leaf { |
| 142 | + color: var(--kendo-color-primary-on-subtle); |
| 143 | + background-color: color-mix(in srgb, var(--kendo-color-primary-subtle-active) 70%, transparent); |
| 144 | + border-radius: var(--kendo-border-radius-sm); |
| 145 | + } |
| 146 | +
|
| 147 | + /* Hover */ |
| 148 | + .treeview-selection-width .k-treeview-item-content:hover { |
| 149 | + color: inherit; |
| 150 | + background-color: transparent; |
| 151 | + } |
| 152 | +
|
| 153 | + .treeview-selection-width .k-treeview-item-content:hover .k-treeview-leaf { |
| 154 | + background-color: color-mix(in srgb, var(--kendo-color-on-app-surface) 18%, transparent); |
| 155 | + border-radius: var(--kendo-border-radius-sm); |
| 156 | + } |
| 157 | +
|
| 158 | + /* Focus */ |
| 159 | + .treeview-selection-width .k-treeview-item-content.k-focus { |
| 160 | + box-shadow: none; |
| 161 | + outline: none; |
| 162 | + } |
| 163 | +
|
| 164 | + .treeview-selection-width .k-treeview-item-content.k-focus .k-treeview-leaf { |
| 165 | + box-shadow: inset 0 0 0 2px var(--kendo-color-border-alt); |
| 166 | + } |
| 167 | +</style> |
| 168 | +
|
| 169 | +@code { |
| 170 | + private IEnumerable<TreeItem> FlatData { get; set; } = new List<TreeItem>(); |
| 171 | + private IEnumerable<object> TreeViewSelectedItems { get; set; } = new List<TreeItem>(); |
| 172 | + private IEnumerable<object> ExpandedItems { get; set; } = new List<TreeItem>(); |
| 173 | +
|
| 174 | + private int TreeLevels { get; set; } = 3; |
| 175 | + private int RootItems { get; set; } = 2; |
| 176 | + private int ItemsPerLevel { get; set; } = 2; |
| 177 | + private int IdCounter { get; set; } = 1; |
| 178 | +
|
| 179 | + protected override void OnInitialized() |
| 180 | + { |
| 181 | + FlatData = LoadFlat(); |
| 182 | +
|
| 183 | + ExpandedItems = FlatData.Where(x => x.HasChildren == true); // && x.ParentId == null |
| 184 | + } |
| 185 | +
|
| 186 | + private List<TreeItem> LoadFlat() |
| 187 | + { |
| 188 | + List<TreeItem> items = new List<TreeItem>(); |
| 189 | +
|
| 190 | + PopulateChildren(items, null, 1); |
| 191 | +
|
| 192 | + return items; |
| 193 | + } |
| 194 | +
|
| 195 | + private void PopulateChildren(List<TreeItem> items, int? parentId, int level) |
| 196 | + { |
| 197 | + var itemCount = level == 1 ? RootItems : ItemsPerLevel; |
| 198 | + for (int i = 1; i <= itemCount; i++) |
| 199 | + { |
| 200 | + var itemId = IdCounter++; |
| 201 | + items.Add(new TreeItem() |
| 202 | + { |
| 203 | + Id = itemId, |
| 204 | + Text = $"Level {level} Item {i}", |
| 205 | + ParentId = parentId, |
| 206 | + HasChildren = level < TreeLevels |
| 207 | + }); |
| 208 | +
|
| 209 | + if (level < TreeLevels) |
| 210 | + { |
| 211 | + PopulateChildren(items, itemId, level + 1); |
| 212 | + } |
| 213 | + } |
| 214 | + } |
| 215 | +
|
| 216 | + public class TreeItem |
| 217 | + { |
| 218 | + public int Id { get; set; } |
| 219 | + public int? ParentId { get; set; } |
| 220 | + public bool HasChildren { get; set; } |
| 221 | + public string Text { get; set; } = string.Empty; |
| 222 | + public object? Icon { get; set; } |
| 223 | +
|
| 224 | + } |
| 225 | +} |
| 226 | +```` |
| 227 | + |
| 228 | +## See Also |
| 229 | + |
| 230 | +* [Override Telerik CSS theme styles](slug:themes-override) |
| 231 | +* [TreeView Selection](slug:treeview-selection-overview) |
| 232 | +* [TreeView Overview](slug:treeview-overview) |
0 commit comments