【问题标题】:How to prevent going to next row after editing a DataGridViewTextBoxColumn and pressing EnterKey?编辑 DataGridViewTextBoxColumn 并按 Enter 键后如何防止进入下一行?
【发布时间】:2017-02-22 22:39:39
【问题描述】:

我正在使用DataGridViews 开发一个程序。 在一个DatagridView 中有一个DataGridViewTextBoxColumn,它可以被用户编辑。当用户在其中输入完数字后,他按键盘上的 ENTER 键。现在DataGridView 完成了所有Events,毕竟Events,最后一件事就是问题所在。

一切都完成了,Windows 将选择下一个DataGridViewRow,我无法阻止这种情况。

我试过了

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

在我发现的几乎所有事件中。可悲的是,当DataGridViewTextBoxColumn 未处于编辑模式时,我只能阻止 ENTER 键。

这是我在编辑时找到 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(),但最后一个“输入”将是视图中的最后一件事。

有人知道如何预防吗?

【问题讨论】:

标签: c# datagridview focus keypress datagridviewtextboxcell


【解决方案1】:

我尝试通过继承自定义列来更改 Grid 的 Enter 行为 文本框列并覆盖以下事件

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

因此,它不是发送 Enter 键,而是模拟 Tab 的操作,该操作将移动到下一个单元格。希望这会有所帮助

【讨论】:

  • 也是一个好方法。也谢谢你!
【解决方案2】:

嗯,我设法得到了一些可以满足你要求的东西(或者至少完成了最困难的部分,我认为你已经完成了大部分其他工作),但解决方案让我皮肤发痒。

我最终在编辑单元格时“取消”输入键事件以使用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);
    }
} 

您需要对此进行彻底测试,以确保它完全符合您的需要。我只检查了当从编辑控件中按下回车时它确实停止了行更改。

正如我所说 - 我对需要做这样的事情不太满意 - 它感觉很脆弱,而且还可能有奇怪的副作用。但是,如果您必须具有这种行为,并且您对其进行了很好的测试,我认为这是做您想做的事情的唯一方法。

【讨论】:

  • 这对我来说很好用。当我试图离开DataGridViewCheckBoxCell 时,只有一个小错误,我不能设置resetRow,因为它会将我的注意力集中在复选框中。 if (dataGridView1.CurrentCell is DataGridViewCheckBoxCell) resetRow = false; 我正在使用 SelectedRow 而不是更改 CurrentCell 属性,这在我的测试中效果不佳......现在很好,为此非常感谢!
【解决方案3】:
Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
    If e.KeyData = Keys.Enter Then e.Handled = True
End Sub

这只是一种解决方法,不是真正的解决方案,但它确实有效。

【讨论】:

    【解决方案4】:

    你可以简单地做到这一点......

    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..运行程序看看。

    【讨论】:

      【解决方案5】:

      我知道很久以前就有人问过这个问题,但答案可能对那些将来搜索的人有用,我希望如此。最好的解决方案是使用您的自定义列和文本框很容易,因为我们将利用内置类

      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);
          }
      }
      

      【讨论】:

        【解决方案6】:

        这个答案真的来晚了……

        但我遇到了完全相同的问题,不想缓存行等。 所以我四处搜索,这是我对这个问题的解决方案。感谢How to prevent an Enter key press from ending EditMode in a 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
        

        【讨论】:

          【解决方案7】:

          只要这样做,它就会正常工作。

          private void dataGridViewX1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
              {
          
                  SendKeys.Send("{UP}");
                  SendKeys.Send("{Right}");
              }
          

          【讨论】:

            【解决方案8】:

            如果您只需要在输入时关闭表单,您可以使用以下代码。我想网格是只读的,你不需要区分按下回车的情况。

            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);
                }      
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-11-01
              • 1970-01-01
              • 1970-01-01
              • 2020-01-21
              • 1970-01-01
              • 1970-01-01
              • 2010-10-09
              相关资源
              最近更新 更多