Home > Net >  New row default values from datagridview dissappear when another control is selected
New row default values from datagridview dissappear when another control is selected

Time:12-27

This is my first question here so please be merciful with me.

Purpose:

What I want to accomplish is to allow users to edit rows from a DataGridView (which is binded to a List of objects of custom class) in a Windows Forms application. Also, when a new row is generated in the DataGridView, I need to provide some default values, which I am implementing with the DefaultValuesNeeded event handler from the DataGridView.

Problem: When editing a row, user must be able to navigate outside the DataGridView (for example, to a TextBox to provide extra info), but if the user leaves the new row before editing it, default values dissapear from the row. This is what I need to avoid. If user edits any cell of the new row and then clicks somewhere else in the form, all the values in the row remain there, which is correct and the desired behaviour.

I have created a little project to illustrate this. Form:

Imports System.ComponentModel

Public Class Form1
    Private Sub dgvAsientos_DefaultValuesNeeded(sender As Object, e As Windows.Forms.DataGridViewRowEventArgs) Handles DataGridView1.DefaultValuesNeeded

        e.Row.Cells("ID").Value = Me.DataGridView1.Rows.Count
        e.Row.Cells("Name").Value = "Test Name " & Me.DataGridView1.Rows.Count
        e.Row.Cells("Description").Value = "Description " & Me.TextBox1.Text & " " & Me.DataGridView1.Rows.Count
        Me.DataGridView1.BindingContext(Me.DataGridView1.DataSource, Me.DataGridView1.DataMember).EndCurrentEdit()

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim myList As New BindingList(Of ExampleClass)
        For n = 0 To 5
            Dim itemn As New ExampleClass
            itemn.ID = n
            itemn.Name = "Name_" & n
            itemn.Description = "Description_" & n
            itemn.OptionalField = "OptionalField_" & n

            myList.Add(itemn)
        Next
        Dim bs As New BindingSource()
        bs.DataSource = myList
        Me.DataGridView1.DataSource = bs
    End Sub
End Class

Example class:

Public Class ExampleClass
    Public Property ID As Integer
    Public Property Name As String
    Public Property Description As String
    Public Property OptionalField As String    
End Class

Any help will be appreciated. I have found very little info regarding DefaultValuesNeeded BindingSources values lost when user focusing some other control; some of them made me add the line following line, but I didn't find that made any difference.

(...).EndCurrentEdit()

I also found suggestions to add a handler for the binding source AddingNew event which returned an instance of the object with the default values I need, again no difference.

  Private Sub myBindingSource_AddingNew(sender As Object, e As AddingNewEventArgs)    
        e.NewObject = CreateNewExample()
  End Sub

I hope the question and the format is correct. Thanks in advance, MBD

CodePudding user response:

When the user adds a new row in DataGridView by navigating to the last row and then leave the row before editing the cells; in this case, adding the row will be cancelled. It's because of some internal logic which cancels the new row when the row is not dirty.

To change this behavior, you can handle RowValidating or RowLeave events, then notify the current cell is dirty, and then end the current edit.

C# Example

private void dgv1_RowLeave(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex == dgv1.NewRowIndex)
    {
        dgv1.NotifyCurrentCellDirty(true);
        dgv1.BindingContext[dgv1.DataSource, dgv1.DataMember].EndCurrentEdit();
        dgv1.NotifyCurrentCellDirty(false);
    }
}

VB.NET Example

Private Sub dgv1_RowLeave(sender As Object, e As DataGridViewCellEventArgs) _
Handles dgv1.RowLeave

    If e.RowIndex = dgv1.NewRowIndex Then
        dgv1.NotifyCurrentCellDirty(True)
        dgv1.BindingContext(dgv1.DataSource, dgv1.DataMember).EndCurrentEdit()
        dgv1.NotifyCurrentCellDirty(False)
    End If
End Sub
  • Related