SfDataGrid Right-Click (Mouse Event) - Xamarin Forms

I have been trying to figure out a right-click detection/event for Xamarin.Forms.UWP so I can load a context menu when users are on desktop using mouse and keyboard. I have gotten all of the functionality with a context menu but am unable to find a way to detect a right click similar to the demo project below. ListViewItem is a generic Xamarin Forms class belonging to its parent control ListView. However since DataGrid does not come with vanilla XF, I have been unable to find an equivalent for SfDataGrid in VisualStudio or in SyncFusion Documents after about a week. If anyone would be able to guide me towards the SfDataGrid's equivalent of ListViewItem or a way to detect a right click from GridTappedEventArgs I would be extremely grateful.

https://github.com/SyncfusionExamples/How-to-perform-the-right-click-action-in-the-listview-in-xamarin-forms-UWP-platform

7 Replies

KK Karthikraja Kalaimani Syncfusion Team March 5, 2020 02:09 PM UTC

Hi Brandon,

Thank you for contacting Syncfusion support.

We have checked your query and currently we are validating your requirement and we will validate and update you further details on 9th March 2020. We appreciate your patience until then.

Regards,
Karthik Raja
 



KK Karthikraja Kalaimani Syncfusion Team March 9, 2020 03:14 PM UTC

Hi Brandon,

Thank you for your patience.

Based on our architecture currently we don’t have a support for your requirement. So, we are checking feasibility and update you further details on 11th March 2020. We appreciate your patience until then.

Regards,
Karthik Raja 



KK Karthikraja Kalaimani Syncfusion Team March 11, 2020 10:51 AM UTC

Hi Brandon,

Thank you for your patience.

Your requirement can be achieved by using the Custom StackLayout and writing the renderer for Custom StackLayout to detect the RightButtonPressed of the Mouse button. For more details please refer to the below code example and attached sample.

Code Example,

 
[XAML]
…..
<RelativeLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> 
            <syncfusion:SfDataGrid 
            x:Name="dataGrid" 
             ItemsSource="{Binding OrderInfoCollection}" 
             AutoGenerateColumns="True" 
               RelativeLayout.WidthConstraint="{ConstraintExpression 
            Type=RelativeToParent,Property=Width,Constant=0}" 
        RelativeLayout.HeightConstraint="{ConstraintExpression 
            Type=RelativeToParent,Property=Height,Constant=0}" 
            ColumnSizer="Auto"> 
            </syncfusion:SfDataGrid> 
            <local:CustomStackLayout x:Name="stack" BackgroundColor="Red" RelativeLayout.XConstraint="0" d:RelativeLayout.YConstraint="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></local:CustomStackLayout> 
        </RelativeLayout>
….

[C#]
//MainPage.cs
private
SfPopupLayout popupLayout; 
        public MainPage() 
        { 
            InitializeComponent(); 
            stack.RightButtonPressed += RightButtonPressed1; 
            popupLayout = new SfPopupLayout(); 
            this.dataGrid.GridLoaded += DataGrid_GridLoaded; 
        } 
 
        private void DataGrid_GridLoaded(object sender, GridLoadedEventArgs e) 
        { 
            this.dataGrid.WidthRequest = this.dataGrid.GetVisualContainer().ExtentWidth; 
            this.dataGrid.HeightRequest = this.dataGrid.GetVisualContainer().ExtentHeight; 
            this.stack.WidthRequest = this.dataGrid.GetVisualContainer().ExtentWidth; 
            this.stack.HeightRequest = this.dataGrid.GetVisualContainer().ExtentHeight; 
        } 
 
        private void RightButtonPressed1(object sender, EventArgs e) 
        { 
            popupLayout.Show(Helper.PositionX, Helper.PositionY); 
        }

//CustomStackLayout
public class CustomStackLayout : StackLayout 
    { 
 
        public EventHandler RightButtonPressed; 
 
        public CustomStackLayout() 
        { 
 
        } 
 
        protected override void LayoutChildren(double x, double y, double width, double height) 
        { 
            base.LayoutChildren(x, y, width, height); 
        } 
 
        public void RaiseEventHandler(double x, double y) 
        { 
            if (this.RightButtonPressed != null) 
            { 
                Helper.PositionX = x; 
                Helper.PositionY = y; 
                this.RightButtonPressed(this,EventArgs.Empty); 
            } 
        } 
    }

//Helder.cs
public static class Helper 
    { 
        public static double PositionX; 
 
        public static double PositionY; 
    }


//Renderer class for CustomStackLayout
public class StackRenderer : VisualElementRenderer<CustomStackLayout, Control> 
    { 
        public StackRenderer() 
        { 
            this.PointerPressed += StackRenderer_PointerPressed;   
        } 
 
        private void StackRenderer_PointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) 
        { 
            Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint((sender as Button)); 
            if (ptrPt.Properties.IsRightButtonPressed) 
            { 
                 
                this.Element.RaiseEventHandler(ptrPt.Position.X, ptrPt.Position.Y);    
            } 
        } 
    } 
 

Sample :  https://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGridDemo1101267619897900588.zip

We hope this helps, please let us know if need further assistance from us.

Regards,
Karthik Raja



BR Brandon March 11, 2020 04:59 PM UTC

Hi Karthikraja,

Thank you very much, this solution was above and beyond and exactly what I was looking for! I am currently building a cross-platform application highly dependent on Syncfusion UI and am extremely satisfied with your product and quick support thus far. I am looking forward to continued testing of your product and am confident we will decide to implement it fully once we have made more progress with our project. Your time and effort are greatly appreciated and I am enjoying the Syncfusion experience thus far!

Best Regards,
Brandon


KK Karthikraja Kalaimani Syncfusion Team March 12, 2020 07:18 AM UTC

Hi Brandon,

Thank you for the update. We glad to know that your requirement has been achieved. Please let us know if you have any further queries on this. We are happy to help you.

Regards,
Karthik Raja 



BR Brandon July 20, 2020 07:43 PM UTC

Figured this out a while back, providing if SyncFusion would want to expand your documentation for those targeting UWP and using SfDataGrid. All developers would have to do is find where Helper.PositionY/point.Y is right below column headers and set that as "var Offset = (point.Y)". Much easier/accurate than converting point to RowColumnIndex from my time invested.
```
public YourPage()
{
     if (Device.RuntimePlatform == Device.UWP)
     {
                CreateContextMenu();
                stack.LeftButtonPressed += LeftButtonPressed;
                stack.RightButtonPressed += RightButtonPressed;           
     }
}
StackLayout contextMenu;
Button SelectButton;
Button ClearButton;
public void CreateContextMenu()
        {
            contextMenu = new StackLayout();
            SelectButton = new Button();
            SelectButton.Text = "Select All";
            SelectButton.Clicked += SelectButton_Clicked;

            ClearButton = new Button();
            ClearButton.Margin = new Thickness(0, -8, 0, 0);
            ClearButton.Text = "Clear All";
            ClearButton.Clicked += ClearButton_Clicked;

            contextMenu.Children.Add(SelectButton);
            contextMenu.Children.Add(ClearButton);
        }
private void SelectButton_Clicked(object sender, EventArgs e)
        {
               relative.Children.Remove(contextMenu);
               //Do Whatever with RightClickedModel
         }
private void ClearButton_Clicked(object sender, EventArgs e)
        {
            relative.Children.Remove(contextMenu);
            //Do Whatever with RightClickedModel
        }


private void LeftButtonPressed(object sender, EventArgs e)
        {
             if (relative.Children.Contains(contextMenu))
            {
                relative.Children.Remove(contextMenu);
            }
            Model item;
            Point point = new Point(Helper.PositionX, Helper.PositionY);
            var Offset = yyy; //(Pixel Below Headers)
            var Vert = Math.Floor(point.Y-Offset);
            var Index = (DataGridName.GetVisualContainer().VScrollBar.Value - 40)/50; //40 is the default HeaderHeight and 50 is the default Row Height
            if (Vert< 0 || Vert > stack.Height)
            {
                //Headers
            }
            else if (Vert > 0 && Vert < stack.Height)
            {
                var Row = (int)((Vert / 50) + Index);
                if(Row <= ViewModel.DataGridItems.Count - 1)
                {
                    item = ViewModel.DataGridItems[Row];
                    if (item != null)
                    {
                        if (DataGridName.SelectedItems.Contains(item))
                        {
                            DataGridName.SelectedItems.Remove(item);
                        }
                        else
                        {
                            DataGridName.SelectedItems.Add(item);
                        }
                    }
                }
            }
        }

private Model RightClickedModel { get; set; }

private void RightButtonPressed(object sender, EventArgs e)
        {
            if (relative.Children.Contains(contextMenu))
            {
                relative.Children.Remove(contextMenu);
            }
            Model item;
            Point point = new Point(Helper.PositionX, Helper.PositionY);
            var Offset = yyy; //(Pixel Below Headers)         
            var Vert = Math.Floor(point.Y - Offset);
            var Index = (DataGridName.GetVisualContainer().VScrollBar.Value - 40) / 50;
            if (Vert < 0 || Vert > stack.Height)
            {
                //Headers
            }
            else if (Vert > 0 && Vert < stack.Height)
            {
                var Row = (int)((Vert / 50) + Index);
                if (Row <= ViewModel.DataGridItems.Count - 1)
                {
                    item = ViewModel.DataGridItems[Row];
                    if (item != null)
                    {
                        RightClickedModel = item;
                    }
                    relative.Children.Add(contextMenu, Constraint.Constant(point.X), Constraint.Constant(Vert));
                }
            }
        }
```


KK Karthikraja Kalaimani Syncfusion Team July 21, 2020 11:58 AM UTC

Hi Brandon,

Thank for the information. We will log this as KB in future
 

Regards,
Karthik Raja
 


Loader.
Up arrow icon