如何在编辑DataGridViewTextBoxColumn并按Enter键后阻止进入下一行?

时间:2011-04-24 16:02:41

标签: c# datagridview focus keypress datagridviewtextboxcell

我正在制作一个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(),但最后一次“输入”将是视图中的最后一件事。

有人知道如何防止这种情况吗?

8 个答案:

答案 0 :(得分:9)

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

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

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

答案 1 :(得分:6)

好吧,我设法得到了一些可以做你想要的东西(或者至少做了很难的部分,我认为你已经完成了大部分其他工作)但是解决方案让我的皮肤爬行。

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

您需要彻底测试,以确保它完全符合您的需要。我只是检查了当按下编辑控件的输入时它确实停止了行更改。

正如我所说 - 我不太乐意需要做这样的事情 - 它感觉很脆弱,而且它可能会产生奇怪的副作用。但是如果你必须有这种行为,并且你测试得很好,我认为这是你想要的唯一方法。

答案 2 :(得分: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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

你可以做到这一点......

1 ...为该网格视图创建KeyDown事件。(转到gridview上的属性并双击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 :(得分:1)

这个答案真的来晚了......

但我有完全相同的问题,并且不想缓存行等。 所以我用Google搜索,这是我对问题的解决方案。致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

答案 6 :(得分:0)

只需这样就可以正常工作。

-(void)uploadImage
 {
NSString *userCategory = self.UserCategory;
NSDictionary *dict = [self.arrayWithImages objectAtIndex:self.currentIndex];
NSString *notes = [dict objectForKey:@"string"];
UIImage *sample = [dict objectForKey:@"image"];
NSData *sampleData = UIImageJPEGRepresentation(sample, 1.0);
NSMutableDictionary *FinalDict = [self.dictMetaData mutableCopy];
[FinalDict setObject:userCategory forKey:@"user_category"];
if (notes.length > 0) {
[FinalDict setObject:notes forKey:@"note"];
}
for (int i = 0; i<self.arrayWithImages.count; i++) {
[ServerUtility uploadImageWithAllDetails:FinalDict noteResource:sampleData andCompletion:^(NSError *error,id data)
{
if (!error) {
NSString *strResType = [data objectForKey:@"res_type"];
                       if ([strResType.lowercaseString isEqualToString:@"success"]) {

                           NSLog(@"Upload Successfully");
                           self.currentIndex++;
                           }

                       else if ([strResType.lowercaseString isEqualToString:@"error"])

                       {
                           NSString *strMsg = [data objectForKey:@"msg"];

                           [self.view makeToast:strMsg duration:1.0 position:CSToastPositionCenter];
                       }



                   }


                   else{

                        [self.view makeToast:error.localizedDescription duration:1.0 position:CSToastPositionCenter];

                   }



              }];




}

答案 7 :(得分:-1)

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

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