简体   繁体   中英

C# DataGridView Adding a Row - When validating, how do I know the row is new and not yet committed?

I have a client having a problem with a DataGridView in a Windows app. They are calling the CellValidated event, but they want to have different validation for the cell if it is in a row that is already committed back to the datasource than if it is a row that is first being added (and not yet committed (the user hasn't left the row yet). I tried the IsNewRow property, but as soon as you start typing in the row, another "new row" is added, so the row you are working with is no longer considered the new row. I know the row has not been committed yet because you can hit Esc to cancel editing, and the entire row goes away.

Is there a way to tell if the currently edited row is actually the "new row" in the sense that it hasn't been committed back to the datasource?

One way I've achieved something similar in the past is to utilise the id property of my objects that are bound to the list.

For example, if I have a BindingList<User> where user is something like:

public class Names
{
    public string Name { get; set; }         
    public int id { get; set; }
}

I can then bind my list like this:

dataGridView1.AutoGenerateColumns = false;
_users = new BindingList<User>();
_users .Add(new Names() { Name = "joe", id=1 });
_users .Add(new Names() { Name = "pete", id = 2 });

bindingSource1.DataSource = _names;

DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
col1.DataPropertyName = "Name";        

dataGridView1.Columns.Add(col1);

dataGridView1.DataSource = _users;

Then, when the DataGridView provides a new row, it will have an id of 0 (the default value for an integer).

Every object that comes from the database has a non zero id.

There may also be a way to achieve this using BindingSources but I had a quick look over the properties there and nothing leaped out at me.

What is the data source in this case?

If it's a datatable, then you can easily test the DataRowState property of the datatable's rows to see if they are new or existing. Once you've validated your datarows, you can then call an Accept on the table to commit those rows. There is no need to interfere between the grid and it's datatable, in this situation.

Of course, this doesn't mean your data is actually committed to a database, if that's where it's finally stored. That would be another step.

Also, I usually avoid directly writing to a datagridview; instead, I make it read-only and pop up an add/entry screen which can perform any validation required.

I don't know if any of this has been of use to you - if I've missed the point please let me know.

This should help people that aren't using DataTable objects:

In the CellBeginEdit event set the Tag property to some value that you will use to differentiate the 'new' row

private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    if (e.RowIndex == dataGridView1.NewRowIndex)
        dataGridView1.Rows[e.RowIndex].Tag = true;
}

Then in your validating event you can check for that value:

if (dataGridView1.Rows[e.RowIndex].Tag is bool 
    && (bool) dataGridView1.Rows[e.RowIndex].Tag)
{
    // new row code

    // after it's added, mark it as 'not new'
    dataGridView1.Rows[e.RowIndex].Tag = false;
}
else
{
    // existing row code
}

GenericMeatUnit's answer didn't work for me, but it provided me with enough to find a way to make it work. Here's how I am doing the check now:

if (this.DATASET.DATATABLE.Rows.Count == e.RowIndex)

This if statement works because before leaving the row in the DataGridView, it doesn't actually exist in the datatable yet, so the number of rows in the datatable will be equal to the RowIndex for the new row, since RowIndex is zero-based.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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