Articles in this section
Category / Section

How to add a context menu to TreeView in Xamarin.Forms

3 mins read

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();
}

View sample in GitHub

TreeView-Xamarin-ContextMenu

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied