简体   繁体   English

DataGridView-单元格验证-防止CurrentRow / Cell更改

[英]DataGridView - cell validation - prevent CurrentRow/Cell change

I have WinForms DataGridView with source set to SortableBindingList . 我有WinForms DataGridView ,其源设置为SortableBindingList In this form, there's column Comment and I need to prevent user from inserting some characters, thus validation. 在此表单中,有Comment )列,我需要防止用户插入某些字符,从而进行验证。

What I want to do is, whenever user enters invalid value, system will notify him ( OnNotification( 'You entered wrong comment'); ) and force him/her to stay in edit mode. 我想做的是,每当用户输入无效值时,系统都会通知他( OnNotification( 'You entered wrong comment'); )并强迫他/她保持编辑模式。

So far I build solution like this: 到目前为止,我建立了这样的解决方案:

void MyDataGridView_CellEndEdit( object sender, DataGridViewCellEventArgs e )
{
    if (e.ColumnIndex == ColumnComment.Index) {
        object data = Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
        if( (data != null) && (!CommentIsValid( data.ToString()))){
            CurrentCell = Rows[e.RowIndex].Cells[e.ColumnIndex];
            BeginEdit( true );

            // My notification method
            OnNotification( String.Format( "Comment `{0}` contains invalid characters) );
            return;
        }
    }
}

I have following issues with this: 我对此有以下问题:

  • OnCellValidating is triggered only when whole form is closing or when current row is changed, not after I finish editing of single cell , so I've put check into CellEndEdit . 仅当关闭整个表单或更改当前行时才触发OnCellValidating ,而不是在我完成单个单元格的编辑之后才触发,因此我将检查置于CellEndEdit
  • When I used Enter / Esc to end editing, it works as expected and desired. 当我使用Enter / Esc结束编辑时,它可以按预期和期望的方式工作。
  • When I use mouse and click to another row, cell stays in edit mode, but another row gets selected. 当我使用鼠标并单击到另一行时,单元格保持在编辑模式,但是另一行被选中。
  • When I try to use Enter (displays notification on invalid comment) and then Esc (to cancel edit) it uses value pushed by Enter (because edit mode has finished). 当我尝试使用Enter (在无效评论上显示通知),然后使用Esc (取消编辑)时,它将使用Enter 推入的值(因为编辑模式已完成)。

So my questions are : 所以我的问题是

  • How can I fire CellValidating after each cell edit, not when form is closing 如何在每次单元格编辑后触发CellValidating ,而不是在窗体关闭时触发
  • How can I prevent CurrentRow and CurrentCell change even after mouse click? 即使单击鼠标后,如何防止CurrentRowCurrentCell更改?
  • How can I force cell to stay in edit mode? 如何强制单元格保持在编辑模式?

When I use mouse and click to another row, cell stays in edit mode, but another row gets selected. 当我使用鼠标并单击到另一行时,单元格保持在编辑模式,但是另一行被选中。

Here I would use a global Boolean, bool isInvalidState say and a global DataGridViewCell = invalidCell object. 在这里,我将使用全局布尔值, bool isInvalidState说和全局DataGridViewCell = invalidCell对象。 In the default state you can set isInvalidState = false and invalidCell = null . 在默认状态下,可以设置isInvalidState = falseinvalidCell = null Then using 然后使用

private bool OnNotification(string cellValue)
{
    // Check for error.
    if (error)
        return false;
}

Then in the above method 然后在上面的方法

void MyDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == ColumnComment.Index) {
        object data = Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
        if((data != null) && (!CommentIsValid(data.ToString()))){
            CurrentCell = Rows[e.RowIndex].Cells[e.ColumnIndex];
            BeginEdit(true);

            // My notification method
            isInvalidState = OnNotification(
                String.Format("Comment `{0}` contains invalid characters));
            if (isInvalidState)
                invalidCell = MyDataGridView[e.RowIndex, e.ColumnIndex];
            return;
        }
    }
}

Now, wire-up an event CellContentClick on your DataGridView and check if isInvalidState == true 现在,在DataGridView上连接一个事件CellContentClick并检查isInvalidState == true

private void MyDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (isInvlaidState)
    {
        isInvalidState = false;
        MyDataGridView.CurrentCell = invalidCell;
        invalidCell = null;
        return;
    }
    // Do other stuff here.
}

When I try to use Enter (displays notification on invalid comment) and then Esc (to cancel edit) it uses value pushed by Enter (because edit mode has finished). 当我尝试使用Enter(在无效评论上显示通知),然后使用Esc(取消编辑)时,它将使用Enter推入的值(因为编辑模式已完成)。

I am not sure about this problem; 我不确定这个问题。 it is likely you will have to handle the KeyDown event and capture the escape key - handling it differently. 您可能必须处理KeyDown事件并捕获转义键-以不同的方式处理它。

I hope this helps. 我希望这有帮助。

Try something like this. 尝试这样的事情。 It shall work. 它会工作。

private void datagridview1_dataGridview_CellValidating
(object sender, DataGridViewCellValidatingEventArgs e) 
{
    if (datagridview1_dataGridview.Rows[e.RowIndex].Cells[2].Value.Equals(""))
    {
         MessageBox.Show("Product name should not be empty", "Error");
         datagridview1_dataGridview.CurrentCell = datagridview1_dataGridview.Rows[e.RowIndex].Cells[2];
         datagridview1_dataGridview.CurrentCell.Selected = true;
    }
}

Unfortunately, MoonKnight's solution didn't work fully for me as the code in CellContentClick event handler never set the control back to the cell that was being validated for its value, when it had an invalid value. 不幸的是,MoonKnight的解决方案对我而言并不完全有效,因为CellContentClick事件处理程序中的代码从未将控件设置回被验证为其值有效的单元格(当它具有无效值时)。 Nevertheless, considering his valuable hint of using global variables isInvalidState and invalidCell helped me constructing the following solution that works exactly as asked in the OP. 尽管如此,考虑到他使用全局变量isInvalidStateinvalidCell宝贵提示,它帮助我构建了以下解决方案,该解决方案完全符合OP中的要求。

Using the combination of CellValidating and CellValidated in the right way solves the problem as follows: 正确使用CellValidatingCellValidated的组合可解决以下问题:

Do your data validation inside the CellValidating event handler. CellValidating事件处理程序中进行数据验证。 Set the isInvalidState flag and the cellWithInvalidUserInput variable (NOTE: I renamed the invalidCell to cellWithInvalidUserInput ): 设置isInvalidState标志和cellWithInvalidUserInput变量(注意:我将invalidCell重命名为cellWithInvalidUserInput ):

private void MyDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    var cellUnderConsideration = MyDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];

    if (!ValidateCurrentCellValue(cellUnderConsideration)) 
    {               
       OnNotification( String.Format( "Comment `{0}` contains invalid characters) );
       //Or MessageBox.Show("your custom message");

       isInvalidState = true;
       cellWithInvalidUserInput = cellUnderConsideration;
       e.Cancel = true;                    
    }
}

The data validation function: 数据验证功能:

bool isInvalidState;
DataGridViewCell cellWithInvalidUserInput;
private bool ValidateCurrentCellValue(DataGridViewCell cellToBeValidated)
{
    //return 'true' if valid, 'false' otherwise
}

Perform desired actions on UI controls inside the CellValidated event handler: CellValidated事件处理程序内的UI控件上执行所需的操作:

private void MyDataGridView_CellValidated(object sender, DataGridViewCellEventArgs e)
{
    if (isInvalidState)
    {
        isInvalidState = false;

        if (cellWithInvalidUserInput != null && cellWithInvalidUserInput.RowIndex > -1)
        {
            MyDataGridView.CurrentCell = cellWithInvalidUserInput;
            MyDataGridView.CurrentCell.Selected = true;
            MyDataGridView.BeginEdit(true);
        }

        cellWithInvalidUserInput = null;
    }
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM