Selecting GridCells Programmatically

7 posts, 0 answers
  1. Glenn
    Glenn avatar
    7 posts
    Member since:
    Oct 2007

    Posted 18 Feb 2015 Link to this post

    Hi Telerik Folks,

    We've overridden our "ProcessKey(KeyEventArgs keys) in a customized BaseGridBehavior class that we're using.  In doing this, the default keys for selecting a block of cells (Shift + the arrow keys) are no longer working.

    To overcome this we're trying to put in custom code to explicitly do the same thing.  It looks like this...

    01.    public class MyGridBehavior : BaseGridBehavior
    02.    {
    03. 
    04. 
    05.        public void SelectCellBlock(GridViewCellInfo SelectedCellTopLeft,GridViewCellInfo SelectedNewCell)
    06.        {
    07.            this.GridControl.ClearSelection();
    08. 
    09. 
    10.            int TopRowIndex = SelectedCellTopLeft.RowInfo.Index <= SelectedNewCell.RowInfo.Index ? SelectedCellTopLeft.RowInfo.Index : SelectedNewCell.RowInfo.Index;
    11.            int BottomRowIndex = SelectedCellTopLeft.RowInfo.Index >= SelectedNewCell.RowInfo.Index ? SelectedCellTopLeft.RowInfo.Index : SelectedNewCell.RowInfo.Index;
    12. 
    13.            int LeftColumnIndex = SelectedCellTopLeft.ColumnInfo.Index <= SelectedNewCell.ColumnInfo.Index ? SelectedCellTopLeft.ColumnInfo.Index : SelectedNewCell.ColumnInfo.Index;
    14.            int RightColumnIndex = SelectedCellTopLeft.ColumnInfo.Index >= SelectedNewCell.ColumnInfo.Index ? SelectedCellTopLeft.ColumnInfo.Index : SelectedNewCell.ColumnInfo.Index;
    15. 
    16.            //this.GridControl.GridNavigator.BeginSelection(new GridNavigationContext() { InputType = InputType.Keyboard, ModifierKeys = Keys.Shift });
    17. 
    18.            for (int rowIndex = TopRowIndex; rowIndex <= BottomRowIndex; rowIndex++)
    19.            {
    20.                for (int columnIndex = LeftColumnIndex; columnIndex <= RightColumnIndex; columnIndex++)
    21.                {
    22.                    this.GridControl.Rows[rowIndex].Cells[columnIndex].IsSelected = true;
    23.                }
    24.            }
    25.        }
    26. 
    27.        public override bool ProcessKey(KeyEventArgs keys)
    28.        {
    29. 
    30.            if (keys.Shift && keys.KeyCode ==Keys.Down)
    31.            {               
    32.                GridViewCellInfo SelectedCellTopLeft = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    33.                this.GridControl.GridNavigator.SelectNextRow(1);
    34.                GridViewCellInfo SelectedNewCell = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    35.                SelectCellBlock(SelectedCellTopLeft, SelectedNewCell);
    36.                return false;
    37.                     
    38.            }
    39. 
    40.            if (keys.Shift && keys.KeyCode == Keys.Up)
    41.            {
    42.                GridViewCellInfo SelectedCellTopLeft = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    43.                this.GridControl.GridNavigator.SelectPreviousRow(1);
    44.                GridViewCellInfo SelectedNewCell = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    45.                SelectCellBlock(SelectedCellTopLeft, SelectedNewCell);
    46.                return false;
    47. 
    48.            }
    49. 
    50.            if (keys.Shift && keys.KeyCode == Keys.Left)
    51.            {               
    52.                GridViewCellInfo SelectedCellTopLeft = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    53.                this.GridControl.GridNavigator.SelectPreviousColumn();
    54.                GridViewCellInfo SelectedNewCell = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    55.                SelectCellBlock(SelectedCellTopLeft, SelectedNewCell);
    56.                return false;
    57.            }
    58. 
    59.            if (keys.Shift && keys.KeyCode == Keys.Right)
    60.            {
    61.                GridViewCellInfo SelectedCellTopLeft = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    62.                this.GridControl.GridNavigator.SelectNextColumn();
    63.                GridViewCellInfo SelectedNewCell = this.GridControl.SelectedCells.OrderBy(r => r.RowInfo.Index).ThenBy(c => c.ColumnInfo.Index).FirstOrDefault();
    64.                SelectCellBlock(SelectedCellTopLeft, SelectedNewCell);
    65.                return false ;
    66.            }
    67.      }
    68.}


    ...It works, pretty much but it's performance gets exponentially slower the larger the block of cells that is selected holding down the Shift key.  It does this most likely because it loops through every cell and individually selects and flips the "IsSelected" property.

    Is there a more efficient way to select blocks of cells, like using the GridNavigator.BeginSelection?  Is there a sample for using the GridNavigationContext parameter to do it this way given two cell addresses?

    Are we going about this the wrong way?  Is there a more efficient way to make it opt out of our ProcessKey override and have it use the default behavior?

    Thanks for any help you can provide...
  2. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4004 posts

    Posted 23 Feb 2015 Link to this post

    Hello Glenn,

    Thank you for writing.

    I am not familiar with the complete scenario. However, note that grid selection is performed in the GridDataRowBehavior. When you replace the BaseGridBehavior with your custom implementation and override the ProcessKey method, you stop the basic logic for selection. Afterwards, you clear the entire selection and perform it again iterating through the cells. It is normal in this situation to experience some selection delay. Could you please give us  more detailed explanation about the exact functionality that you are trying to achieve and why it is necessary to clear the selection and perform it again with processing arrow keys?

    By default, when arrow keys are used with Shift the SelectNextRow, SelectPreviousRow, SelectPreviousColumn, SelectNextColumn methods are wrapped around Navigator.BeginSelection ​and Navigator.EndSelection block. Here is a sample code snippet demonstrating how to keep the default selection logic without noticing any slow down execution. Feel free to extend it on a way to accomplish your requirement:
    public Form1()
    {
        InitializeComponent();
     
        this.radGridView1.MultiSelect = true;
        this.radGridView1.SelectionMode = Telerik.WinControls.UI.GridViewSelectionMode.CellSelect;
     
        //register the custom row  behavior
        BaseGridBehavior gridBehavior = radGridView1.GridBehavior as BaseGridBehavior;
        gridBehavior.UnregisterBehavior(typeof(GridViewDataRowInfo));
        gridBehavior.RegisterBehavior(typeof(GridViewDataRowInfo), new CustomGridDataRowBehavior());
    }
     
    public class CustomGridDataRowBehavior : GridDataRowBehavior
    {
        public override bool ProcessKey(KeyEventArgs keys)
        {
            if (keys.Shift && keys.KeyCode == Keys.Down)
            {
                this.GridViewElement.Navigator.BeginSelection(this.GetKeyboardNavigationContext(keys));
                this.GridViewElement.Navigator.SelectNextRow(1);
                this.GridViewElement.Navigator.EndSelection();
                return true;
            }
     
            if (keys.Shift && keys.KeyCode == Keys.Up)
            {
                this.GridViewElement.Navigator.BeginSelection(this.GetKeyboardNavigationContext(keys));
                this.GridViewElement.Navigator.SelectPreviousRow(1);
                this.GridViewElement.Navigator.EndSelection();
                return true;
            }
     
            if (keys.Shift && keys.KeyCode == Keys.Left)
            {
                this.GridViewElement.Navigator.BeginSelection(this.GetKeyboardNavigationContext(keys));
                if (this.GridViewElement.RightToLeft)
                {
                    if (!(this.GridViewElement.Navigator.IsLastRow(this.GridViewElement.CurrentRow) &&
                          this.GridViewElement.Navigator.IsLastColumn(this.GridViewElement.CurrentColumn)))
                    {
                        this.GridViewElement.Navigator.SelectNextColumn();
                    }
                }
                else
                {
                    if (!(this.GridViewElement.Navigator.IsFirstRow(this.GridViewElement.CurrentRow) &&
                          this.GridViewElement.Navigator.IsFirstColumn(this.GridViewElement.CurrentColumn)))
                    {
                        this.GridViewElement.Navigator.SelectPreviousColumn();
                    }
                }
                this.GridViewElement.Navigator.EndSelection();
     
                return true;
            }
     
            if (keys.Shift && keys.KeyCode == Keys.Right)
            {
                this.GridViewElement.Navigator.BeginSelection(this.GetKeyboardNavigationContext(keys));
                if (this.GridViewElement.RightToLeft)
                {
                    if (!(this.GridViewElement.Navigator.IsFirstRow(this.GridViewElement.CurrentRow) &&
                          this.GridViewElement.Navigator.IsFirstColumn(this.GridViewElement.CurrentColumn)))
                    {
                        this.GridViewElement.Navigator.SelectPreviousColumn();
                    }
                }
                else
                {
                    if (!(this.GridViewElement.Navigator.IsLastRow(this.GridViewElement.CurrentRow) &&
                          this.GridViewElement.Navigator.IsLastColumn(this.GridViewElement.CurrentColumn)))
                    {
                        this.GridViewElement.Navigator.SelectNextColumn();
                    }
                }
     
                this.GridViewElement.Navigator.EndSelection();
                return true ;
            }
            return base.ProcessKey(keys);
        }
    }

    I hope this information helps. Should you have further questions, I would be glad to help.
     
    Regards,
    Dess
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Glenn
    Glenn avatar
    7 posts
    Member since:
    Oct 2007

    Posted 23 Feb 2015 Link to this post

    Hello Dess, thanks very much for your reply.  

    Your posted solution works great!  

    It looks like we can get a lot better control Overriding the ProcessKey() on the GridDataRowBehavior class rather than the BaseGridBehavior class.  ...We migrated our custom Hot-Key code to the GridDataRowBehavior's ProcessKey() override and put it below the code you provided to preserve the default Selection behavior.  

    Thanks very much for your help!


  4. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4004 posts

    Posted 26 Feb 2015 Link to this post

    Hello Glenn,

    Thank you for writing back.

    I am glad the suggested approach suits your requirement. If you have any additional questions, please let me know.

    Regards,
    Dess
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Gone2TheDogs
    Gone2TheDogs avatar
    66 posts
    Member since:
    May 2016

    Posted 19 Feb 2018 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    The users for my Winform will be using Keyboard only. I have a read-only grid that needs to be traversed using the arrow keys. I'm using VB.Net and tried to convert the C# code listed as a solution in this thread. The code fails at line 5. (keys.KeyCode.Down). How is this piece translated in vb.net?

    01.Public Class CustomGridDataRowBehavior
    02.    Inherits GridDataRowBehavior
    03.     
    04.    Public Overrides function ProcessKey(keys As KeyEventArgs) as boolean  
    05.        If keys.KeyCode = keys.KeyCode.Down Then
    06.            Me.GridViewElement.Navigator.BeginSelection(Me.GetKeyboardNavigationContext(keys))
    07.            Me.GridViewElement.Navigator.SelectNextRow(1)
    08.            Me.GridViewElement.Navigator.EndSelection
    09.            Return True
    10.        End If
    11.    End function
    12. 
    13. 
    14. 
    15. 
    16.End Class

     

  6. Gone2TheDogs
    Gone2TheDogs avatar
    66 posts
    Member since:
    May 2016

    Posted 19 Feb 2018 in reply to Gone2TheDogs Link to this post

    I am also getting an error on the following code in vb.net also:

    Line 2 and 3. GridViewDataRowInfo is a class type

    1.Dim gridBehavior As BaseGridBehavior = dgvAllPrintQueues.GridBehavior
    2.gridBehavior.UnregisterBehavior(TypeOf (GridViewDataRowInfo))
    3.gridBehavior.RegisterBehavior(TypeOf (GridViewDataRowInfo), New CustomGridDataRowBehavior())
  7. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    4004 posts

    Posted 20 Feb 2018 Link to this post

    Hello, Bob, 

    Thank you for writing.  

    You can refer to the following help article demonstrating how to unregister and register a custom row behavior : https://docs.telerik.com/devtools/winforms/gridview/rows/row-behaviors

    Feel free to use our online code converter to convert C# to VB and vice versa: http://converter.telerik.com/

    I hope this information helps. Should you have further questions I would be glad to help. 
     
     Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top