Can I use Arrow keys instead of Enter

May 1, 2009 at 9:41 AM
I want to have functionality like excel where after I have changed the value of a cell, the arrow keys will accept the change like enter does and then move in the direction of the arrow key.
I tried overriding OnKeyPress and OnKeyDown to try an intercept the arrow key events but they don't trigger when I am actually editing the cell.
What do I need to do?
Thanks
David
May 26, 2009 at 11:12 PM

I am working on the same thing.  The editor for the cell captures the key before it goes to your keyDown event. 

Create a PreviewKeyPress event handler for your editior.

In there, you can check for the arrow keys (right arrow is keyvalue 39 for example) and act accordingly.

In my case, I apply the edit then move to the next cell to the right unless it is the last cell in the row.

The only problem I am having at the moment is trying to figure out if the arrow keys are being used to move around the text that is being edited.  If you figure that one out, please let me know

Jun 16, 2009 at 3:25 PM

Thanks,  I'll implement that event handler tomorrow. 

I think I will add in a check to see if the caret is at the end of the text in the cell.  If you are at the end of the text and you hit the right key, then move to the next cell, if not, let it do what it normally does i.e. move the caret.  The same can apply to the right movement.  Up and Down will always move to the appropriate cells.  Not sure how to do this yet, but I am sure we canget access to the contents of the cell from the event handler.

Jun 24, 2009 at 8:43 AM

I've had a few issues with creating the PreviewKeyPress event handler.  I create it but it only ever catches the event while the caret isn't in the cell.  Where chould I be creating this event handler to capture the event before the cell eats the event?

Jun 24, 2009 at 1:13 PM
Could you not just add an event handler to the cell when you build them to call your existing handler?
 
Sorta like if you are adding a bunch of lables to a dialog, but want the click handler to pass to the form, you just add the += OnClick to the lable and move on.
 
Hope that helps.
~D
On Wed, Jun 24, 2009 at 4:44 AM, wavey <notifications@codeplex.com> wrote:

From: wavey

I've had a few issues with creating the PreviewKeyPress event handler.  I create it but it only ever catches the event while the caret isn't in the cell.  Where chould I be creating this event handler to capture the event before the cell eats the event?

Read the full discussion online.

To add a post to this discussion, reply to this email (sourcegrid@discussions.codeplex.com)

To start a new discussion for this project, email sourcegrid@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Jul 20, 2009 at 4:41 PM

After doing some other things I finally got round to properly looking at this problem.

I've got it working as I require.  Hopefully this may be of use to someone else if they have the same problem.


The functionality checks to see if the caret is at the end or beginning of the text in the cell, and moves to the cell to the right or left appropriately when an arrow key is hit, i.e. if the caret is inside the text then it just moves through the text, but at the ends it will shift focus to another cell.
It always shifts to another cell on up and down arrows

This only works on DevAgeTextBox cell types

So, here is the code...

in SourceGrid/Cells/Editors/EditorControlBase.cs I add a new event handler

        private void AttachControl(GridVirtual grid)
        {
            mGrid = grid;
            mLinkedControl = new LinkedControlValue(Control, Position.Empty);
            Control.Hide();
            grid.LinkedControls.Add(mLinkedControl);
            Control.Validated += new EventHandler(InnerControl_Validated);
            Control.KeyPress += new KeyPressEventHandler(InnerControl_KeyPress);
            Control.PreviewKeyDown += new PreviewKeyDownEventHandler(InnerControl_PreviewKeyDown);
        }

and then the code in the handler method is as follows

        private void InnerControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            // if we are looking at a text box then work out if we need to move about
            if (sender.GetType().Name == "DevAgeTextBox")
            {
                DevAge.Windows.Forms.DevAgeTextBox editor = (DevAge.Windows.Forms.DevAgeTextBox)sender;

                // where is the caret in the textbox? Returns an index of the charater on the right of the caret
                int caretPos = editor.SelectionStart - editor.GetFirstCharIndexOfCurrentLine() + 1;

                // what cell position are we in?
                Position cellPos = mGrid.Selection.ActivePosition;

                if (cellPos == Position.Empty)
                    return;

                // if we move right and we are at the end of a set of text then move to the cell on the right
                if (e.KeyCode == Keys.Right)
                {
                    // is there cell to the right to move to?
                    if (cellPos.Column != mGrid.Columns.Count - 1)
                    {
                        // check if we are at the end of the text
                        if (caretPos > editor.Text.Length)
                        {
                            // if we are then move to the cell on the right
                            Position newPos = new Position(cellPos.Row, cellPos.Column + 1);
                            mGrid.Selection.Focus(newPos, true);
                        }
                    }
                }

                // if we hit left and the caret is at the start if the text then move to the cell on the left if it exists
                if (e.KeyCode == Keys.Left)
                {
                    // is there cell to the left to move to?
                    if (cellPos.Column != 0)
                    {
                        // check if we are at the start of the text
                        if (caretPos == 1)
                        {
                            // if we are then move to the cell on the left
                            Position newPos = new Position(cellPos.Row, cellPos.Column - 1);
                            mGrid.Selection.Focus(newPos, true);
                        }
                    }
                }

                // if down is hit, then always move to the cell below if it is there
                if (e.KeyCode == Keys.Down)
                {
                    // is there a cell below to move to?
                    if (cellPos.Row != mGrid.Rows.Count - 1)
                    {
                        // if there is then move down
                        Position newPos = new Position(cellPos.Row + 1, cellPos.Column);
                        mGrid.Selection.Focus(newPos, true);
                    }
                }

                // if up is hit, then always move to the cell above if it is there
                if (e.KeyCode == Keys.Up)
                {
                    // is there a cell above to move to?
                    if (cellPos.Row != 0)
                    {
                        // if there is then move up
                        Position newPos = new Position(cellPos.Row - 1, cellPos.Column);
                        mGrid.Selection.Focus(newPos, true);
                    }
                }
            }           
        }

Jul 27, 2009 at 7:32 AM

Exactly what I wanted to do.

But it's better when somebody does it for you! Nice work, thanks.

Aug 25, 2009 at 4:24 AM

Great contribution David! Thanks.

I have created a slightly modified version that inherits from SourceGrid.Cells.Editors.TextBox

With this class you don't have to modify the sourcegrid codebase, but you do have to modify your own code - set the cell's Editor property to new TextBox2();

Cheers,

Darren

 


using System;
using System.Collections.Generic;
using System.Text;
using SourceGrid.Cells.Editors;
using SourceGrid;

namespace MyProject.Grids.Cells.Editors
{
    class TextBox2 : TextBox
    {
        public TextBox2(Type p_Type)
            : base(p_Type)
        {
        }

        protected override void OnStartingEdit(CellContext cellContext, System.Windows.Forms.Control editorControl)
        {
            base.OnStartingEdit(cellContext, editorControl);
            Control.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(InnerControl_PreviewKeyDown);
        }

        void InnerControl_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
        {
            // where is the caret in the textbox? Returns an index of the charater on the right of the caret
            int caretPos = Control.SelectionStart - Control.GetFirstCharIndexOfCurrentLine() + 1;

            // what cell position are we in?
            Position cellPos = EditCellContext.Position;

            if (cellPos == Position.Empty)
                return;

            // if we move right and we are at the end of a set of text then move to the cell on the right
            if (e.KeyCode == System.Windows.Forms.Keys.Right)
            {
                // is there cell to the right to move to?
                if (cellPos.Column != Grid.Columns.Count - 1)
                {
                    // check if we are at the end of the text
                    if (caretPos > Control.Text.Length)
                    {
                        // if we are then move to the cell on the right
                        Position newPos = new Position(cellPos.Row, cellPos.Column + 1);
                        Grid.Selection.Focus(newPos, true);
                    }
                }
            }

            // if we hit left and the caret is at the start if the text then move to the cell on the left if it exists
            if (e.KeyCode == System.Windows.Forms.Keys.Left)
            {
                // is there cell to the left to move to?
                if (cellPos.Column != 0)
                {
                    // check if we are at the start of the text
                    if (caretPos == 1)
                    {
                        // if we are then move to the cell on the left
                        Position newPos = new Position(cellPos.Row, cellPos.Column - 1);
                        Grid.Selection.Focus(newPos, true);
                    }
                }
            }

            // if down is hit, then always move to the cell below if it is there
            if (e.KeyCode == System.Windows.Forms.Keys.Down)
            {
                // is there a cell below to move to?
                if (cellPos.Row != Grid.Rows.Count - 1)
                {
                    // if there is then move down
                    Position newPos = new Position(cellPos.Row + 1, cellPos.Column);
                    Grid.Selection.Focus(newPos, true);
                }
            }

            // if up is hit, then always move to the cell above if it is there 
            if (e.KeyCode == System.Windows.Forms.Keys.Up)
            {
                // is there a cell above to move to?
                if (cellPos.Row != 0)
                {
                    // if there is then move up
                    Position newPos = new Position(cellPos.Row - 1, cellPos.Column);
                    Grid.Selection.Focus(newPos, true);
                }
            }
        }
    }
}

 

 

Coordinator
Sep 3, 2009 at 10:05 AM

Great work guys.

 

What do you think of including this functionality (one or another way) into SourceGrid?

Sep 3, 2009 at 10:51 AM

I'd love to see it in there, but then I would say that as I need the functionality :o)

Sep 15, 2009 at 4:18 AM

Sounds good to me too. Maybe a property can be added to optionally disable the feature? "ArrowKeysCanEndEdit" or something :) this way the code could go into the regular sourcegrid version of TextBox.

What do you guys think?

Sep 15, 2009 at 5:30 AM

I've created a patch implementing this, see issue http://sourcegrid.codeplex.com/WorkItem/View.aspx?WorkItemId=3989

Oct 30, 2012 at 3:07 PM

Hi,

I was trying just this (albeit in vb.net) and the 'OnStartingEdit' method in my derived class never seems to be called

Public

Class TextEd2

 Inherits SourceGrid.Cells.Editors.TextBox

Public Sub New ()

 MyBase.New(GetType(String))

 

Me.AllowNull = True   

End Sub

P

rotected Overrides Sub OnStartingEdit(cellContext As SourceGrid.CellContext, editorControl As System.Windows.Forms.Control
)

 

  MyBase.OnStartingEdit(cellContext, editorControl)

  AddHandler Control.PreviewKeyDown, AddressOf HandleKeyPreview  End Sub

Private

 

Sub HandleKeyPreview(sender As Object, e As PreviewKeyDownEventArgs)

  'Handle the key preview

End Sub



Any thoughts?