Selecting GridCells Programmatically

4 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
    Admin
    Dess avatar
    1601 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. UI for WinForms is Visual Studio 2017 Ready
  4. 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!


  5. Dess
    Admin
    Dess avatar
    1601 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.

     
Back to Top