picoe / Eto

Cross platform GUI framework for desktop and mobile applications in .NET
Other
3.67k stars 335 forks source link

TreeGridView Right-click select + context menu #2225

Open devmaestro1 opened 2 years ago

devmaestro1 commented 2 years ago

Hello,

I am using a TreeGridView and trying to replicate the typical Windows Explorer behavior where a right-click selects an item and brings up the context menu. My CellClick event implementation is shown below:

  private void Grid_CellClick(object sender, GridCellMouseEventArgs e)
        {
            if (e.Buttons == MouseButtons.Alternate)
            {
                 if (e.Item is ITreeGridItem)
                 { 
                    // It seems it is necessary to set the current selection
                    // as null first, otherwise multiple selection will occur
            grid.SelectedItem = null;
                    grid.SelectedItem = (ITreeGridItem)e.Item;
                 }
            }
        }

I am unfortunately finding that my implemented solution doesn't always work. In some unknown situations, the CellClick event does not seem to be fired, resulting in a context menu being shown, but no selection taking place.

It seems that I can "reactivate" the CellClick event by firstly left-clicking on the item. The right-click will then again trigger the CellClick event but only one or so times before it stops responding again.

Does anyone know what I might be doing wrong?

Out of interest, it seems that I can use native events to implement the behavior, as shown below, however this solution isn't ideal as it won't work on other platforms.

private void NativeMouseEvent(object sender, EventArgs e)
{
   System.Windows.Forms.MouseEventArgs x = (System.Windows.Forms.MouseEventArgs)e;
   var cell = grid.GetCellAt(new PointF(x.Location.X, x.Location.Y));
   if ( cell != null)
   {
      if ( cell.Item is ITreeGridItem )
      {
         grid.SelectedItem = null;
     grid.SelectedItem = (ITreeGridItem)cell.Item;
       }
    }
   OnSelectedItemChanged(sender, e);
   if (x.Button == System.Windows.Forms.MouseButtons.Right)
   {
      if (grid.ContextMenu != null)
      {
         grid.ContextMenu.Show();
      }
   }
}

Specifications

cwensley commented 2 years ago

Have you tried using the MouseDown event vs. CellClick? It might work better for you without having to resort to native events. I also would like the right click on windows to automatically select the item under the cursor if not already selected, it seems like a better user experience than the default behaviour.

devmaestro1 commented 2 years ago

Hi @cwensley , thanks for the rapid response! I have attempted your suggestion as shown below however, it again seems to be plagued by the random missing "MouseDown" events. I have break-pointed the start of the MouseDown event and it seems that it is not being called for some reason.

For the record, both the native Mouse Event and the CellClick events are not hooked.

At the moment, I can't see any pattern to the behavior. Sometimes it works perfectly for several clicks and then for a series of clicks, nothing will happen.

private void Grid_MouseDown(object sender, MouseEventArgs e) {
    if (e.Buttons == MouseButtons.Alternate) {
        var loc = e.Location;
        var cell = grid.GetCellAt(new PointF(loc.X, loc.Y));
        if (cell != null) {
            if (cell.Item is ITreeGridItem) {
                grid.SelectedItem = null;
                grid.SelectedItem = (ITreeGridItem) cell.Item;

                if (grid.ContextMenu != null) {
                    grid.ContextMenu.Show();
                }
            }
        }
    }
}