diff --git a/_contentTemplates/common/event-arguments.md b/_contentTemplates/common/event-arguments.md new file mode 100644 index 0000000000..3f9669f2f3 --- /dev/null +++ b/_contentTemplates/common/event-arguments.md @@ -0,0 +1,31 @@ +#rowclick-args + +The event arguments expose an `EventArgs` property. It maps to `MouseEventArgs` or `KeyboardEventArgs` depending on the user's action (clicking the row with the mouse/tapping it on a touch device, or pressing `Enter` when the row is focused). You can use the event arguments to determine the keyboard key or the position of the mouse cursor when the user took an action. + +#end + +#rowclick-args-example + + if (args.EventArgs is KeyboardEventArgs keyboardEventArgs) + { + Console.WriteLine($"The user clicked {keyboardEventArgs.Key} on row {model.Name}"); + } + else if (args.EventArgs is MouseEventArgs mouseEventArgs) + { + Console.WriteLine($"The user clicked {mouseEventArgs.ClientX} {mouseEventArgs.ClientY} on row {model.Name}"); + } + +#end + +#rowclick-args-treeview-example + + if (args.EventArgs is KeyboardEventArgs keyboardEventArgs) + { + Console.WriteLine($"The user clicked {keyboardEventArgs.Key} on node {item.Text}"); + } + else if (args.EventArgs is MouseEventArgs mouseEventArgs) + { + Console.WriteLine($"The user clicked {mouseEventArgs.ClientX} {mouseEventArgs.ClientY} on node {item.Text}"); + } + +#end \ No newline at end of file diff --git a/_contentTemplates/grid/common-link.md b/_contentTemplates/grid/common-link.md index 6e35a119c3..97a7672ca9 100644 --- a/_contentTemplates/grid/common-link.md +++ b/_contentTemplates/grid/common-link.md @@ -3,26 +3,6 @@ #end -#rowclick-args - -The `GridRowClickEventArgs` class exposes an `EventArgs` property. It maps to `MouseEventArgs` or `KeyboardEventArgs` depending on the user's action (clicking the row with the mouse/tapping it on a touch device, or pressing `Enter` when the row is focused). You can use the event arguments to determine the keyboard key or the position of the mouse cursor when the user took an action. - -#end - -#rowclick-args-example - - if (args.EventArgs is KeyboardEventArgs keyboardEventArgs) - { - Console.WriteLine($"The user clicked {keyboardEventArgs.Key} on row {model.Name}"); - } - else if (args.EventArgs is MouseEventArgs mouseEventArgs) - { - Console.WriteLine($"The user clicked {mouseEventArgs.ClientX} {mouseEventArgs.ClientY} on row {model.Name}"); - } - -#end - - #conditional-style-row-and-cell-render ````CSHTML @* Conditional styling/formatting for a cell and row *@ diff --git a/components/contextmenu/integration.md b/components/contextmenu/integration.md index 66888ac719..0a475e0b2c 100644 --- a/components/contextmenu/integration.md +++ b/components/contextmenu/integration.md @@ -27,6 +27,7 @@ This article provides the following two examples: * [Know The Target And Adjust Items](#know-the-target-and-adjust-items) * [Context Menu for a Grid Row](#context-menu-for-a-grid-row) +* [Context Menu for a TreeView Node](#context-menu-for-a-treeview-node) You can apply the approach of hooking to your own events to show the context menu in other scenarios as well. For example, you can [add a context menu for your treeview nodes]({%slug contextmenu-kb-treeview-item%}). @@ -37,11 +38,12 @@ Hooking to your own HTML elements' events lets you determine what to do with the >caption Use the context menu target and change menu items based on the target data ````CSHTML -@* Get context menu target and alter its items based on it *@ +@* Get context menu target and alter its items based on it *@ + TextField="Text" SeparatorField="Separator" IconField="Icon" + DisabledField="Disabled" + OnClick="@( (ContextMenuItem itm) => ContextMenuClickHandler(itm) )"> @@ -77,7 +79,7 @@ Hooking to your own HTML elements' events lets you determine what to do with the MenuItems[2].Items[0].Disabled = clickedItem.IsSpecial; } - async Task ClickHandler(ContextMenuItem clickedItem) + async Task ContextMenuClickHandler(ContextMenuItem clickedItem) { // handle the command from the context menu by using the stored metadata if (!string.IsNullOrEmpty(clickedItem.CommandName) && LastClickedItem != null) @@ -92,7 +94,7 @@ Hooking to your own HTML elements' events lets you determine what to do with the { MenuItems = new List() - { + { new ContextMenuItem { Text = "More Info", @@ -107,7 +109,7 @@ Hooking to your own HTML elements' events lets you determine what to do with the { Text = "Advanced", Items = new List() - { + { new ContextMenuItem { Text = "Delete", @@ -171,8 +173,8 @@ Hooking to your own HTML elements' events lets you determine what to do with the To integrate the context menu with the Telerik Grid, you need to: -1. Use the grid's `OnRowContextMenu` event to get the current row model and show the menu -2. Use the context menu's `OnClick` event to handle the desired operation +1. Use the grid's [`OnRowContextMenu`]({%slug grid-events%}#onrowcontextmenu) event to get the current row model and show the menu +2. Use the context menu's [`OnClick`]({%slug contextmenu-events%}#onclick) event to handle the desired operation In this example, the context menu is used to select/deselect items, put an item in edit mode and delete items @@ -182,7 +184,9 @@ In this example, the context menu is used to select/deselect items, put an item @using System.Collections.Generic @using System.Collections.ObjectModel - + + () - { + { new MenuItem(){ Text = "Select", Icon="checkbox-checked", CommandName="ToggleSelect" }, new MenuItem(){ Text = "Edit", Icon="edit", CommandName="BeginEdit" }, new MenuItem(){ Text = "Delete", Icon="delete", Action = DeleteItem } @@ -383,6 +387,200 @@ In this example, the context menu is used to select/deselect items, put an item } ```` +## Context Menu for a TreeView Node + +To integrate the ContextMenu with the TreeView, you need to: + +1. Use the [`OnItemContextMenu`]({%slug treeview-events%}#onitemcontextmenu) event of the TreeView to get the current row model and show the menu +2. Use the context menu's [`OnClick`]({%slug contextmenu-events%}#onclick) event to handle the desired operation + +In this example, the context menu is used to select/deselect items and delete items + +>caption Use a Context Menu for TreeView nodes + +````CSHTML +@* Use the OnItemContextMenu event of the TreeView to show the ContextMenu for its items *@ + + + + + + + +@code { + private TelerikContextMenu ContextMenu { get; set; } + + public TreeItem LastClickedItem { get; set; } + + public IEnumerable SelectedItems { get; set; } = new List(); + + public List FlatData { get; set; } + + public List ContextMenuData { get; set; } + + async Task OnItemContextMenuHandler(TreeViewItemContextMenuEventArgs args) + { + LastClickedItem = args.Item as TreeItem; + + if (args.EventArgs is MouseEventArgs mouseEventArgs) + { + await ContextMenu.ShowAsync(mouseEventArgs.ClientX, mouseEventArgs.ClientY); + } + } + + private void ContextMenuClickHandler(ContextMenuItem item) + { + + // Use local code to perform a task such as put select/deselect a node or delete it + switch (item.CommandName) + { + case "ToggleSelect": + var selItems = SelectedItems.ToList(); + if (SelectedItems.Contains(LastClickedItem)) + { + selItems.Remove(LastClickedItem); + } + else + { + selItems.Add(LastClickedItem); + } + SelectedItems = selItems; + SelectedItems = new List(SelectedItems); + break; + + case "InvokeDelete": + FlatData.Remove(LastClickedItem); + FlatData = new List(FlatData); + break; + default: + break; + } + LastClickedItem = null; // clean up + } + + // sample data + + public class ContextMenuItem + { + public string Text { get; set; } + public string Icon { get; set; } + public bool Separator { get; set; } + public string CommandName { get; set; } + } + + public class TreeItem + { + public int Id { get; set; } + public string Text { get; set; } + public int? ParentId { get; set; } + public bool HasChildren { get; set; } + public string Icon { get; set; } + public bool Expanded { get; set; } + } + + protected override void OnInitialized() + { + LoadFlatData(); + + ContextMenuData = new List() + { + new ContextMenuItem + { + Text = "Select", + Icon = "checkbox-checked", + CommandName = "ToggleSelect" + }, + new ContextMenuItem + { + Separator = true + }, + new ContextMenuItem + { + Text = "Delete", + Icon = "delete", + CommandName = "InvokeDelete" + } + }; + } + + private void LoadFlatData() + { + List + items = new List + (); + + items.Add(new TreeItem() + { + Id = 1, + Text = "Project", + ParentId = null, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 2, + Text = "Design", + ParentId = 1, + HasChildren = true, + Icon = "brush", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 3, + Text = "Implementation", + ParentId = 1, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 4, + Text = "site.psd", + ParentId = 2, + HasChildren = false, + Icon = "psd", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 5, + Text = "index.js", + ParentId = 3, + HasChildren = false, + Icon = "js" + }); + items.Add(new TreeItem() + { + Id = 6, + Text = "index.html", + ParentId = 3, + HasChildren = false, + Icon = "html" + }); + items.Add(new TreeItem() + { + Id = 7, + Text = "styles.css", + ParentId = 3, + HasChildren = false, + Icon = "css" + }); + + FlatData = items; + } +} +```` ## See Also diff --git a/components/grid/events.md b/components/grid/events.md index 1af86076dc..58daa11993 100644 --- a/components/grid/events.md +++ b/components/grid/events.md @@ -478,7 +478,7 @@ The `OnRowClick` event fires as a response to the user clicking on a row of the The event handler receives a `GridRowClickEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type. -@[template](/_contentTemplates/grid/common-link.md#rowclick-args) +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) The `OnRowClick` event fires before selection happens. @@ -526,7 +526,7 @@ There is a deliberate delay in the data loading to showcase the async nature of var model = args.Item as SampleData; ProjectData = await GetProjectData(model.Id); - @[template](/_contentTemplates/grid/common-link.md#rowclick-args-example) + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-example) } async Task> GetProjectData(int id) @@ -582,7 +582,7 @@ The `OnRowDoubleClick` event fires as a response to the user double clicking on The event handler receives a `GridRowClickEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type. -@[template](/_contentTemplates/grid/common-link.md#rowclick-args) +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) The `OnRowDoubleClick` event fires before selection happens. @@ -621,7 +621,7 @@ The `OnRowDoubleClick` event fires before selection happens. var model = args.Item as SampleData; logger = $"Double clicked on {model.Name}"; - @[template](/_contentTemplates/grid/common-link.md#rowclick-args-example) + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-example) } @@ -649,9 +649,9 @@ The `OnRowContextMenu` event fires as a response to the user right clicking on a The event handler receives a `GridRowClickEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type. -@[template](/_contentTemplates/grid/common-link.md#rowclick-args) +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) -The `OnRowContextMenu` is used to [integrate the Context menu]({%slug contextmenu-overview%}#context-menu-for-a-grid-row) to the Grid Row. +The `OnRowContextMenu` is used to [integrate the Context menu]({%slug contextmenu-integration%}#context-menu-for-a-grid-row) to the Grid Row. @[template](/_contentTemplates/common/general-info.md#rerender-after-event) @@ -682,7 +682,7 @@ The `OnRowContextMenu` is used to [integrate the Context menu]({%slug contextmen SampleData model = args.Item as SampleData; logger = $"OnRowContextMenu event fired from right clicking on {model.Name}"; - @[template](/_contentTemplates/grid/common-link.md#rowclick-args-example) + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-example) } public IEnumerable MyData = Enumerable.Range(1, 30).Select(x => new SampleData diff --git a/components/treeview/events.md b/components/treeview/events.md index 39d03934e4..e16e46a678 100644 --- a/components/treeview/events.md +++ b/components/treeview/events.md @@ -14,6 +14,8 @@ This article explains the events available in the Telerik TreeView for Blazor: * [OnExpand](#onexpand) * [OnItemClick](#onitemclick) +* [OnItemDoubleClick](#onitemdoubleclick) +* [OnItemContextMenu](#onitemcontextmenu) * [SelectedItemsChanged](#selecteditemschanged) * [CheckedItemsChanged](#checkeditemschanged) @@ -139,7 +141,9 @@ The `OnExpand` event fires when the user expands or collapses a node (either wit ## OnItemClick -The `OnItemClick` event fires when the user clicks (or presses `Enter`) on an node (item) of the TreeView. You can use this event to react on user clicking on a node and load data on demand for another component, for example. +The `OnItemClick` event fires when the user clicks, presses `Enter` or taps (for mobile devices) on an node (item) of the TreeView. You can use this event to react on user clicking on a node and load data on demand for another component, for example. + +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) @[template](/_contentTemplates/common/general-info.md#rerender-after-event) @@ -168,13 +172,15 @@ The `OnItemClick` event fires when the user clicks (or presses `Enter`) on an no public List GridData { get; set; } public List FlatData { get; set; } - async Task OnItemClickHandler(TreeViewItemClickEventArgs e) + async Task OnItemClickHandler(TreeViewItemClickEventArgs args) { - var item = e.Item as TreeItem; + var item = args.Item as TreeItem; ChosenItem = item; //perform actual database operations here GridData = await LoadGridDataOnDemand(ChosenItem.Id); + + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-treeview-example) } #region Data Generation @@ -288,6 +294,281 @@ The `OnItemClick` event fires when the user clicks (or presses `Enter`) on an no } ```` +## OnItemDoubleClick + +The `OnItemDoubleClick` event fires when the user double-clicks or double-taps (for mobile devices) a TreeView node. + +The event handler receives a `TreeViewItemDoubleClickEventArgs` object which provides the model of the clicked node in the `Item` field that you can cast to your model type. + +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) + +@[template](/_contentTemplates/common/general-info.md#rerender-after-event) + +>caption Use the OnItemDoubleClick event to receive information for the clicked node + +````CSHTML +@* Use the OnItemDoubleClick event to receive information for the node the user clicked on *@ + + + + + +@if (!String.IsNullOrEmpty(logger)) +{ +
+ @logger +
+} + +@code { + string logger = String.Empty; + + TreeItem ChosenItem { get; set; } + + public List FlatData { get; set; } + + async Task OnItemDoubleClickHandler(TreeViewItemDoubleClickEventArgs args) + { + var item = args.Item as TreeItem; + + ChosenItem = item; + + logger = $"Double clicked on {item.Text}"; + + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-treeview-example) + + } + + #region Data Generation + + protected override void OnInitialized() + { + LoadFlatData(); + } + + private void LoadFlatData() + { + List items = new List(); + + items.Add(new TreeItem() + { + Id = 1, + Text = "Project", + ParentId = null, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 2, + Text = "Design", + ParentId = 1, + HasChildren = true, + Icon = "brush", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 3, + Text = "Implementation", + ParentId = 1, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 4, + Text = "site.psd", + ParentId = 2, + HasChildren = false, + Icon = "psd", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 5, + Text = "index.js", + ParentId = 3, + HasChildren = false, + Icon = "js" + }); + items.Add(new TreeItem() + { + Id = 6, + Text = "index.html", + ParentId = 3, + HasChildren = false, + Icon = "html" + }); + items.Add(new TreeItem() + { + Id = 7, + Text = "styles.css", + ParentId = 3, + HasChildren = false, + Icon = "css" + }); + + FlatData = items; + } + #endregion + + #region Data Model + + public class TreeItem + { + public int Id { get; set; } + public string Text { get; set; } + public int? ParentId { get; set; } + public bool HasChildren { get; set; } + public string Icon { get; set; } + public bool Expanded { get; set; } + } + #endregion +} +```` + +## OnItemContextMenu + +The `OnItemContextMenu` event fires when the user right-clicks on a TreeView node, presses the context menu keyboard button or taps and holds on a mobile device. + +The event handler receives a `TreeViewItemContextMenuEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type. + +@[template](/_contentTemplates/common/event-arguments.md#rowclick-args) + +The `OnItemContextMenu` is used to [integrate the Context menu]({%slug contextmenu-integration%}#context-menu-for-a-treeview-node) to the TreeView node. + +@[template](/_contentTemplates/common/general-info.md#rerender-after-event) + +>caption Use the OnItemContextMenu event and get the node model + +````CSHTML +@* Get the node information from a context menu action (right click/long tap) *@ + + + + + +@if (!String.IsNullOrEmpty(logger)) +{ +
+ @logger +
+} + +@code { + string logger = String.Empty; + + public List FlatData { get; set; } + + void OnItemContextMenuHandler(TreeViewItemContextMenuEventArgs args) + { + var item = args.Item as TreeItem; + + logger = $"OnItemContextMenu event fired from right clicking on {item.Text}"; + + @[template](/_contentTemplates/common/event-arguments.md#rowclick-args-treeview-example) + } + + #region Data Generation + + protected override void OnInitialized() + { + LoadFlatData(); + } + + private void LoadFlatData() + { + List items = new List(); + + items.Add(new TreeItem() + { + Id = 1, + Text = "Project", + ParentId = null, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 2, + Text = "Design", + ParentId = 1, + HasChildren = true, + Icon = "brush", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 3, + Text = "Implementation", + ParentId = 1, + HasChildren = true, + Icon = "folder", + Expanded = true + }); + + items.Add(new TreeItem() + { + Id = 4, + Text = "site.psd", + ParentId = 2, + HasChildren = false, + Icon = "psd", + Expanded = true + }); + items.Add(new TreeItem() + { + Id = 5, + Text = "index.js", + ParentId = 3, + HasChildren = false, + Icon = "js" + }); + items.Add(new TreeItem() + { + Id = 6, + Text = "index.html", + ParentId = 3, + HasChildren = false, + Icon = "html" + }); + items.Add(new TreeItem() + { + Id = 7, + Text = "styles.css", + ParentId = 3, + HasChildren = false, + Icon = "css" + }); + + FlatData = items; + } + #endregion + + #region Data Model + + public class TreeItem + { + public int Id { get; set; } + public string Text { get; set; } + public int? ParentId { get; set; } + public bool HasChildren { get; set; } + public string Icon { get; set; } + public bool Expanded { get; set; } + } + #endregion +} +```` + ## SelectedItemsChanged The `SelectedItemsChanged` event fires when the [selection]({%slug treeview-selection-overview%}) is enabled and the user clicks on a new item. diff --git a/knowledge-base/contextmenu-treeview-items.md b/knowledge-base/contextmenu-treeview-items.md index 215a472ac9..d1b4e17fdd 100644 --- a/knowledge-base/contextmenu-treeview-items.md +++ b/knowledge-base/contextmenu-treeview-items.md @@ -30,6 +30,8 @@ I would like to add the ContextMenu component to every item (node) in the TreeVi The ContextMenu exposes an API to associate the component to any DOM element through the [ShowAsync]({%slug contextmenu-integration%}) method. You can use the [oncontextmenu](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oncontextmenu) event of an HTML element in the [treeview item template]({%slug components/treeview/templates%}) to show the context menu by using the `MouseEventArgs`. +>tip As of version 2.27, the TreeView exposes [`OnItemContextMenu` event]({%slug treeview-events%}#onitemcontextmenu) that you can use to integrate Telerik Context menu for the TreeView nodes. Here is an example of such a configuration - [Context menu for a TreeView node]({%slug contextmenu-integration%}#context-menu-for-a-treeview-node) + ````CSHTML @* Use the oncontextmenu event of the HTML element to show the ContextMenu for the TreeView items *@