Как предотвратить переход к следующей строке после редактирования DataGridViewTextBoxColumn и нажатия EnterKey? - PullRequest
11 голосов
/ 24 апреля 2011

Я работаю над программой с DataGridViews.В одном DatagridView есть DataGridViewTextBoxColumn, который может редактироваться пользователем.Когда пользователь заканчивает вводить цифры, он нажимает клавишу ВВОД на клавиатуре.Теперь DataGridView делает все свои Events, а после Events последнее - проблема.

Все сделано, и Windows собирается выбрать следующий DataGridViewRow, и я не могу этого предотвратить.

Я пытался

if (e.KeyData == Keys.Enter) e.SuppressKeyPress = true; // or e.Handled 

почти в каждом найденном событии.К сожалению, я смог предотвратить клавишу ВВОД только тогда, когда DataGridViewTextBoxColumn не находится в режиме редактирования.

Вот мой метод, чтобы найти ENTER во время редактирования

Добавление события

private void dgr_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    e.Control.KeyPress += new KeyPressEventHandler(dgr_KeyPress_NumericTester);
}

И это событие для приема только числового ввода.

private void dgr_KeyPress_NumericTester(object sender, KeyPressEventArgs e)
{
    if (!Char.IsDigit(e.KeyChar) && e.KeyChar != 8) e.Handled = true;
}

Чтобы объяснить подробно:

Когда пользователь вводит значение, которое имеет некоторые зависимости, я быЯ хотел бы дать другому элементу управления фокус, поэтому он используется для исправления зависимостей.

Я также пробовал это с DependingControl.Focus(), но последний "ввод" будет последним в представлении.

Кто-нибудь знает, как это предотвратить?

Ответы [ 8 ]

9 голосов
/ 25 апреля 2011

Я пытался изменить поведение Enter для вашей таблицы, унаследовав пользовательский столбец от Столбец текстового поля и переопределение события ниже

protected override bool ProcessDialogKey(Keys keyData)
{
    if (keyData == Keys.Enter)
       return base.ProcessDialogKey(Keys.Tab);
    else
       return base.ProcessDialogKey(keyData);
}

Таким образом, вместо отправляемого ключа ввода он эмулирует действие для Tab, которое переместится в следующую ячейку. Надеюсь, это поможет

6 голосов
/ 25 апреля 2011

Ну, мне удалось заставить работать что-то, что делает то, что вы хотите (или, по крайней мере, выполняет сложную часть, я думаю, что вы уже сделали большинство других вещей), но решение заставляет мою кожу ползти.

Чем я в итоге «отменил» событие клавиши ввода при редактировании ячейки, чтобы использовать смесь события CellEndEdit и события SelectionChanged.

Я ввел пару полей уровня класса, в которых хранится некоторое состояние - в частности, в какой строке мы находимся в конце редактирования ячейки и останавливаются ли изменения в выделении.

Код выглядит так:

public partial class Form1 : Form
{
    private int currentRow;
    private bool resetRow = false;

    public Form1()
    {
        InitializeComponent();

        // deleted out all the binding code of the grid to focus on the interesting stuff

        dataGridView1.CellEndEdit += new DataGridViewCellEventHandler(dataGridView1_CellEndEdit);

        // Use the DataBindingComplete event to attack the SelectionChanged, 
        // avoiding infinite loops and other nastiness.
        dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
    }

    void dataGridView1_SelectionChanged(object sender, EventArgs e)
    {
        if (resetRow)
        {
            resetRow = false;
            dataGridView1.CurrentCell = dataGridView1.Rows[currentRow].Cells[0];          
        }
    }

    void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {
        resetRow = true;
        currentRow = e.RowIndex;
    }

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        dataGridView1.SelectionChanged += new EventHandler(dataGridView1_SelectionChanged);
    }
} 

Вы захотите тщательно проверить это, чтобы убедиться, что оно делает именно то, что вам нужно. Я только проверил, чтобы увидеть, что он останавливает изменение строки при нажатии Enter из элемента управления для редактирования.

Как я уже сказал - я не слишком доволен необходимостью делать что-то подобное - это кажется довольно хрупким, а также может иметь странные побочные эффекты. Но если у вас должно быть такое поведение, и вы хорошо его тестируете, я думаю, что это единственный способ сделать то, что вы хотите.

3 голосов
/ 09 июля 2015
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
    If e.KeyData = Keys.Enter Then e.Handled = True
End Sub

Это просто обходной путь, а не реальное решение, но оно работает.

1 голос
/ 22 февраля 2017

Этот ответ действительно приходит поздно ...

Но у меня была та же проблема, и я не хотел кэшировать строки и т. Д. Так что я погуглил, и это мое решение вопроса. Кредиты на Как предотвратить нажатие клавиши Enter для завершения режима редактирования в DataGridView?

Наследовать от DataGridView и добавить этот код (vb.net):

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
    If Commons.Options.RowWiseNavigation AndAlso Me.IsCurrentCellInEditMode AndAlso (keyData = Keys.Enter Or keyData = Keys.Tab) Then
        ' End EditMode, then raise event, so the standard-handler can run and the refocus is being done
        Me.EndEdit()
        OnKeyDown(New KeyEventArgs(keyData))
        Return True
    End If

    'Default
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function
1 голос
/ 21 марта 2015

Вы можете сделать это просто ....

1 ... Создайте событие KeyDown для этого вида сетки. (Перейдите к свойствам в виде сетки и дважды щелкните событие KeyDown).

2 ... За этим кодом -

if(e.KeyData == Keys.Enter)
{
  e.Handled = true;
}

3 ... Наконец-то это выглядит так.

private void dgvSearchResults_KeyDown(object sender, KeyEventArgs e)
{
  if (e.KeyData == Keys.Enter)
   {
    e.Handled = true;
   }
}

4.. Запустите программу и посмотрите.

1 голос
/ 29 марта 2012

Я знаю, что этот вопрос задавался давным-давно, но ответ может быть полезен для тех, кто ищет в будущем, я надеюсь, что так. Лучшее решение - использовать ваш пользовательский столбец, а для текстового поля это просто, потому что мы воспользуемся встроенными классами

class Native
{
    public const uint WM_KEYDOWN = 0x100;
    [DllImport("user32.dll")]
    public static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
}
//the column that will be added to dgv
public class CustomTextBoxColumn : DataGridViewColumn
{
    public CustomTextBoxColumn() : base(new CustomTextCell()) { }
    public override DataGridViewCell CellTemplate
    {
        get { return base.CellTemplate; }
        set
        {
            if (value != null && !value.GetType().IsAssignableFrom(typeof(CustomTextCell)))
            {
                throw new InvalidCastException("Must be a CustomTextCell");
            }
            base.CellTemplate = value;
        }
    }
}
//the cell used in the previous column
public class CustomTextCell : DataGridViewTextBoxCell
{
    public override Type EditType
    {
        get { return typeof(CustomTextBoxEditingControl); }
    }
}
//the edit control that will take data from user
public class CustomTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    protected override void WndProc(ref Message m)
    {
        //we need to handle the keydown event
        if (m.Msg == Native.WM_KEYDOWN)
        {
            if((ModifierKeys&Keys.Shift)==0)//make sure that user isn't entering new line in case of warping is set to true
            {
                Keys key=(Keys)m.WParam;
                if (key == Keys.Enter)
                {
                    if (this.EditingControlDataGridView != null)
                    {
                        if(this.EditingControlDataGridView.IsHandleCreated)
                        {
                            //sent message to parent dvg
                            Native.PostMessage(this.EditingControlDataGridView.Handle, (uint)m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
                            m.Result = IntPtr.Zero;
                        }
                        return;
                    }
                }
            }
        }
        base.WndProc(ref m);
    }
}

затем мы приходим к самому dgv, я использовал новый класс, производный от DataGridView, добавил мои столбцы и обработал ключ ввода от wndproc также

void Initialize()
{
    CustomTextBoxColumn colText = new CustomTextBoxColumn();
    colText.DataPropertyName = colText.Name = columnTextName;
    colText.HeaderText = columnTextAlias;
    colText.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
    this.Columns.Add(colText);
    DataGridViewTextBoxColumn colText2 = new DataGridViewTextBoxColumn();
    colText2.DataPropertyName = colText2.Name = columnText2Name;
    colText2.HeaderText = columnText2Alias;
    colText2.DefaultCellStyle.WrapMode = DataGridViewTriState.False;
    this.Columns.Add(colText2);
}
protected override void WndProc(ref Message m)
{
    //the enter key is sent by edit control
    if (m.Msg == Native.WM_KEYDOWN)
    {
        if ((ModifierKeys & Keys.Shift) == 0)
        {
            Keys key = (Keys)m.WParam;
            if (key == Keys.Enter)
            {
                MoveToNextCell();
                m.Result = IntPtr.Zero;
                return;
            }
        }
    }

    base.WndProc(ref m);
}

//move the focus to the next cell in same row or to the first cell in next row then begin editing
public void MoveToNextCell()
{
    int CurrentColumn, CurrentRow;
    CurrentColumn = this.CurrentCell.ColumnIndex;
    CurrentRow = this.CurrentCell.RowIndex;
    if (CurrentColumn == this.Columns.Count - 1 && CurrentRow != this.Rows.Count - 1)
    {
        this.CurrentCell = Rows[CurrentRow + 1].Cells[1];//0 index is for No and readonly
        this.BeginEdit(false);
    }
    else if(CurrentRow != this.Rows.Count - 1)
    {
        base.ProcessDataGridViewKey(new KeyEventArgs(Keys.Tab));
        this.BeginEdit(false);
    }
}
0 голосов
/ 05 ноября 2016

Просто сделайте, чтобы все заработало.

private void dataGridViewX1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    {

        SendKeys.Send("{UP}");
        SendKeys.Send("{Right}");
    }
0 голосов
/ 17 сентября 2014

Если вам нужно просто закрыть форму при вводе, вы можете использовать следующий код. Я полагаю, что сетка доступна только для чтения, и вам не нужно выделять ситуацию, в которой был нажат ввод.

public class DataGridViewNoEnter : DataGridView
{       
    protected override bool ProcessDataGridViewKey(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            ((Form)this.TopLevelControl).DialogResult = DialogResult.OK;
            return false;
        }
        return base.ProcessDataGridViewKey(e);
    }      
}
...