How to add a context menu to TreeView in Xamarin.Forms
The Xamarin.Forms SfTreeView allows you to show the popup menu with various menu items to the TreeViewNode.
C#
Define SfPopupLayout to show the menu. Display the popup menu in the ItemHolding event. You can get the touch Position to show the Popup menu from the ItemHoldingEventArgs. For UWP platform, using Renderer, you can show the popup menu on right click. Also, dismiss the Popup when tapping another item.
public class ContextManuBehavior : Behavior<ContentPage> { SfTreeViewExt TreeView; SfPopupLayout popupLayout; KeyDetector KeyDetectorGrid; TreeViewNode Node; FileManagerViewModel ViewModel; protected override void OnAttachedTo(ContentPage bindable) { TreeView = bindable.FindByName<SfTreeViewExt>("treeView"); KeyDetectorGrid = bindable.FindByName<KeyDetector>("keyDetectorGrid"); ViewModel = bindable.BindingContext as FileManagerViewModel; InitializePopupLayout(); TreeView.ItemTapped += TreeView_ItemTapped; if (Device.RuntimePlatform == Device.UWP) { TreeView.ItemRightTapped += TreeView_ItemRightTapped; KeyDetectorGrid.KeyPressed += KeyDetectorGrid_KeyPressed; } else { TreeView.ItemHolding += TreeView_ItemHolding; } base.OnAttachedTo(bindable); } private void InitializePopupLayout() { popupLayout = new SfPopupLayout(); popupLayout.PopupView.HeightRequest = 70; popupLayout.PopupView.WidthRequest = 100; popupLayout.PopupView.ContentTemplate = new DataTemplate(() => { var mainStack = new StackLayout(){ BackgroundColor = Color.FromHex("#a6a9b6"), Spacing = 1 }; var deletedButton = new Button() { Text = "Delete", HeightRequest = 35, BackgroundColor = Color.FromHex("#e8e8e8") }; deletedButton.Clicked += DeletedButton_Clicked; var editButton = new Button() { Text = "Edit", HeightRequest = 35, BackgroundColor = Color.FromHex("#e8e8e8") }; editButton.Clicked += EditButton_Clicked; mainStack.Children.Add(deletedButton); mainStack.Children.Add(editButton); return mainStack; }); popupLayout.PopupView.ShowHeader = false; popupLayout.PopupView.ShowFooter = false; } private void ShowPopup(Point position) { if (position.Y + 100 <= TreeView.Height && position.X + 100 > TreeView.Width) popupLayout.Show((double)(position.X - 100), (double)(position.Y)); else if (position.Y + 100 > TreeView.Height && position.X + 100 < TreeView.Width) popupLayout.Show((double)position.X, (double)(position.Y - 100)); else if (position.Y + 100 > TreeView.Height && position.X + 100 > TreeView.Width) popupLayout.Show((double)(position.X - 100), (double)(position.Y - 100)); else popupLayout.Show((double)position.X, (double)(position.Y)); } private void TreeView_ItemHolding(object sender, Syncfusion.XForms.TreeView.ItemHoldingEventArgs e) { if (popupLayout.IsOpen) popupLayout.Dismiss(); Node = e.Node; ShowPopup(e.Position); } private void TreeView_ItemRightTapped(object sender, ItemRightTappedEventArgs e) { if (popupLayout.IsOpen) popupLayout.Dismiss(); Node = e.ItemData as TreeViewNode; ShowPopup(e.Position); } private void TreeView_ItemTapped(object sender, Syncfusion.XForms.TreeView.ItemTappedEventArgs e) { popupLayout.Dismiss(); } private void KeyDetectorGrid_KeyPressed(object sender, KeyEventArgs e) { if (e.Key == "Escape" || e.Key == "Dismiss") { popupLayout.Dismiss(); } } }
C#
Extend the SfTreeView to raise the right click event. Customize the parent view of the SfTreeView to raise the key inputs.
public class SfTreeViewExt : SfTreeView { public event ItemRightTappedEventHandler ItemRightTapped; public void RaiseItemRightTapped(ItemRightTappedEventArgs e) { if (ItemRightTapped != null) this.ItemRightTapped(this, e); } } public class KeyDetector : Grid { public event KeyPressedEventHandler KeyPressed; public void RaiseKeyPressed(KeyEventArgs e) { if (KeyPressed != null) this.KeyPressed(this, e); } }
XAML
Load the SfTreeView into the custom KeyDetector grid. And customize the ItemTemplate element to raise the right click event for a specific node.
<local:KeyDetector x:Name="keyDetectorGrid"> <StackLayout> <Label Text="TreeView Header" HeightRequest="50" HorizontalOptions="Center" VerticalOptions="Center"/> <local:SfTreeViewExt x:Name="treeView" ChildPropertyName="SubFiles" NodeSizeMode="Dynamic" NotificationSubscriptionMode="CollectionChange" ItemsSource="{Binding ImageNodeInfo}" AutoExpandMode="AllNodesExpanded"> <local:SfTreeViewExt.ItemTemplate> <DataTemplate> <local:CustomGrid x:Name="grid" TreeView="{x:Reference treeView}"> ... </local:CustomGrid> </DataTemplate> </local:SfTreeViewExt.ItemTemplate> </local:SfTreeViewExt> </StackLayout> </local:KeyDetector>
C#
You can also perform action on menu items, such as Delete and Edit, and dismiss the menu once the action is finished.
private void EditButton_Clicked(object sender, EventArgs e) { popupLayout.Dismiss(); var item = Node.Content as FileManager; ShowEditor(item); } private void DeletedButton_Clicked(object sender, EventArgs e) { var item = Node.Content as FileManager; if (Node.ParentNode != null) { var parentNode = Node.ParentNode.Content as FileManager; parentNode.SubFiles.Remove(item); } else ViewModel.ImageNodeInfo.Remove(item); popupLayout.Dismiss(); }