none
DropDownList is only filling alternate rows in DataGridView RRS feed

  • Question

  • This is really bizarre and I could not figure it out.

    Why is the Job_Status and Production_Status filled up in an alternate manner? 
    By default, when user creates a New Row Entry, Job_Status and Production_Status will have a default value set to them.
    But here, I could not figure why only the alternate rows are filled.
    As you can see, there are no problem with other fields, only DropDownList isn't filling the rows properly...

    User creates New Entry by clicking AddNew Button.
    Here I set default values to Job_StatusComboBox & Production_StatusComboBox

    Private Sub AddNew_btn_Click(sender As Object, e As EventArgs) Handles AddNew_btn.Click
            POTextBox.Focus()
            ProjectsBindingSource.AddNew()
    
            'Set Default Text
            Job_StatusComboBox.Text = "On Hold"
            Production_StatusComboBox.Text = "Processing"
            Date_Of_EntryDateTimePicker.Value = DateTime.Now
            Lead_TimeDateTimePicker.Value = DateTime.Now
            Last_UpdatedLabel1.Text = Date.Now.ToString("dd-MM-yyyy HH:mm:ss")
            save_btn.BackColor = Color.DarkGray
    
            AddNew_btn.Enabled = False
        End Sub

    User then click SAVE to commit changes
    Private Sub save_btn_Click(sender As Object, e As EventArgs) Handles save_btn.Click
            AddNew_btn.Enabled = True
            
            Try
                Last_UpdatedLabel1.Text = Date.Now.ToString("dd-MM-yyyy HH:mm:ss")
    
                ProjectsBindingSource.EndEdit()
                ProjectsTableAdapter.Update(EVC_ProjectsDataSet.Projects) 'Name of DB Table
    
                'Refresh the ID in the GridView
                EVC_ProjectsDataSet.Clear()
                ProjectsTableAdapter.Fill(EVC_ProjectsDataSet.Projects)
    
                MessageBox.Show("Data Saved!")
                
                save_btn.BackColor = DefaultBackColor
            Catch ex As Exception
                MessageBox.Show("Error saving data!")
            End Try
    
            loadCellColor()
        End Sub

    Only upon SAVE, the DataGridView will update with the new row.
    So why are only alternate rows having the default value?


    Sunday, May 5, 2019 6:41 AM

Answers

  • Here is the path to the DefaultValue.

    In regards to if the click a different row, check the RowState of the current row by casting the BindingSource.Current to a DataRow which I've shown, if the value is not 1 then they left the new row. There is also an event for the BindingSource, PositionChanged which will tell you they left a row.

    ResetCurrentItem.

    It would be good for you to explore the BindingSource documentation to become familiar with what is possible.

    I also want to say that way too many developers look at a TableAdapter method of working with data and never take time to learn what is possible thus end up doing things like thinking they need to refresh a DataGridView to see changes as you are now and you are far from being the only one, my guess there are thousands of developers who think the same because they never take time to read the documentation which gives you what's needed to not do things like refreshing their DataGridView.

    What I've done when adding/editing with a BindingSource is to always use a child form for this and with that you are insured to be on the same row but that is not for everyone. I've never felt the need to refresh any controls to get the changes.

    Edit another thought on leaving the row is to subscribe to DataError event of the DataGridView. For instance generally speaking a new row has constraints e.g. in this case for my table CompanyName is required, by leaving the row this would raise an exception "Column 'CompanyName' does not allow nulls." so I would check for this e.g.

    Private Sub CustomersDataGridView_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) _
        Handles CustomersDataGridView.DataError
    
        If e.Exception.Message.Contains("does not allow nulls") Then
            CustomersBindingSource.CancelEdit()
            MessageBox.Show("New row aborted")
            e.Cancel = True
        End If
    
    End Sub


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Sunday, May 5, 2019 12:25 PM
    Moderator

All replies

  • Hello,

    I would offer an alternate method to perform the adding of a new record which does not require you to reload the data via 

    EVC_ProjectsDataSet.Clear()
    ProjectsTableAdapter.Fill(EVC_ProjectsDataSet.Projects)

    First off you can set default values for a new row by setting the default value in the .xsd file

    The following parts I'm mocking up. The general idea is to first add a new row. If you inspect AddNew it is a DataRowView (this is important in the next section)

    Private Sub AddButton_Click(sender As Object, e As EventArgs) Handles AddButton.Click
        CustomersBindingSource.AddNew()
    End Sub

    Once the above executes I have the following, a new row with Country set to USA. To simulate setting fields we have another button, remember above I said knowing that AddNew is a DataRowView, we know access it's Row property which is a DataRow and set fields.

    Private Sub UpdateNewRow_Click(sender As Object, e As EventArgs) Handles UpdateNewRow.Click
        Dim row = CType(CustomersBindingSource.Current, DataRowView).Row
        row.SetField("CompanyName", "Best Coffee")
        row.SetField("ContactName", "Karen Payne")
        CustomersBindingSource.ResetCurrentItem()
    End Sub

    If the new row is to be save we use

    Private Sub CustomersBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) _
        Handles CustomersBindingNavigatorSaveItem.Click
    
        Me.Validate()
        Me.CustomersBindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.NorthWindAzureDataSet)
    
    End Sub

    If the user decides to cancel the new row

    Private Sub CancelNewRowButton_Click(sender As Object, e As EventArgs) _
        Handles CancelNewRowButton.Click
    
        CustomersBindingSource.CancelEdit()
    
    End Sub

    That's it other than the need to add proper checks/assertion for things like detecting if required fields have been entered and so forth.

    So the above should never cause strange stuff to happen such as it is now and you have better control over everything.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CustomersTableAdapter.Fill(Me.NorthWindAzureDataSet.Customers)
        End Sub
    
        Private Sub CustomersBindingNavigatorSaveItem_Click(sender As Object, e As EventArgs) _
            Handles CustomersBindingNavigatorSaveItem.Click
    
            Me.Validate()
            Me.CustomersBindingSource.EndEdit()
            Me.TableAdapterManager.UpdateAll(Me.NorthWindAzureDataSet)
    
        End Sub
        ''' <summary>
        ''' Shows how to set a field for the current row in the DataGridView
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub SetButton_Click(sender As Object, e As EventArgs) Handles SetButton.Click
            Dim row = CType(CustomersBindingSource.Current, DataRowView).Row
            row.SetField("ContactName", ContactNameTextBox.Text)
        End Sub
        ''' <summary>
        ''' Quick and dirty method to see all field values for the current row.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub GetButton_Click(sender As Object, e As EventArgs) Handles GetButton.Click
            Dim row = CType(CustomersBindingSource.Current, DataRowView).Row
            Console.WriteLine(String.Join(",", row.ItemArray))
        End Sub
        ''' <summary>
        ''' Add a new blank row, Country column default value is set via assigning a default
        ''' value in the .xsd file, select the table, select Country field, set DefaultValue
        ''' property in this case to USA.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub AddButton_Click(sender As Object, e As EventArgs) Handles AddButton.Click
            CustomersBindingSource.AddNew()
        End Sub
        ''' <summary>
        ''' Press this button after the add button above to set fields, in this case they are
        ''' hard coded but in a real app would comes from form controls like TextBox, ComboBox
        ''' and so forth. Once this executes pressing the Save button in the BindingNavigator
        ''' or manually calling code in CustomersBindingNavigatorSaveItem_Click pushes the 
        ''' changes to the database table.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub UpdateNewRow_Click(sender As Object, e As EventArgs) Handles UpdateNewRow.Click
            Dim row = CType(CustomersBindingSource.Current, DataRowView).Row
            row.SetField("CompanyName", "Best Coffee")
            row.SetField("ContactName", "Karen Payne")
            CustomersBindingSource.ResetCurrentItem()
        End Sub
    
        Private Sub CancelNewRowButton_Click(sender As Object, e As EventArgs) _
            Handles CancelNewRowButton.Click
    
            CustomersBindingSource.CancelEdit()
    
        End Sub
    End Class
    


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Sunday, May 5, 2019 10:52 AM
    Moderator
  • I have no item where you found this property...what is xsd file?

    Which object property do I look at? I don't see DefaultValue.

    I borrowed this, it work I guess, provided the user doesn't click a different row before clicking "SAVE"

     Dim row = CType(ProjectsBindingSource.Current, DataRowView).Row
            row.SetField("Job Status", "On Hold")
            row.SetField("Production Status", "Processing")
     

    Is there anyway to save (ProjectsBindingSource.Current, DataRowView) as a variable in a Sub and use in a different Sub? Basically a variable that can be shared by 2 Subs.

    Private Sub AddNew_btn_Click(sender As Object, e As EventArgs) Handles AddNew_btn.Click
    
    row = CType(ProjectsBindingSource.Current, DataRowView).Row
    
    End Sub
    Private Sub save_btn_Click(sender As Object, e As EventArgs) Handles save_btn.Click
    
    row.SetField("Job_Status", "On Hold")
    row.SetField("Production_Status", "Processing")
    
    End Sub


    What does ResetCurrentItem() do?

    Thanks in advance

    Sunday, May 5, 2019 11:56 AM
  • Here is the path to the DefaultValue.

    In regards to if the click a different row, check the RowState of the current row by casting the BindingSource.Current to a DataRow which I've shown, if the value is not 1 then they left the new row. There is also an event for the BindingSource, PositionChanged which will tell you they left a row.

    ResetCurrentItem.

    It would be good for you to explore the BindingSource documentation to become familiar with what is possible.

    I also want to say that way too many developers look at a TableAdapter method of working with data and never take time to learn what is possible thus end up doing things like thinking they need to refresh a DataGridView to see changes as you are now and you are far from being the only one, my guess there are thousands of developers who think the same because they never take time to read the documentation which gives you what's needed to not do things like refreshing their DataGridView.

    What I've done when adding/editing with a BindingSource is to always use a child form for this and with that you are insured to be on the same row but that is not for everyone. I've never felt the need to refresh any controls to get the changes.

    Edit another thought on leaving the row is to subscribe to DataError event of the DataGridView. For instance generally speaking a new row has constraints e.g. in this case for my table CompanyName is required, by leaving the row this would raise an exception "Column 'CompanyName' does not allow nulls." so I would check for this e.g.

    Private Sub CustomersDataGridView_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) _
        Handles CustomersDataGridView.DataError
    
        If e.Exception.Message.Contains("does not allow nulls") Then
            CustomersBindingSource.CancelEdit()
            MessageBox.Show("New row aborted")
            e.Cancel = True
        End If
    
    End Sub


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Sunday, May 5, 2019 12:25 PM
    Moderator
  • Is there anyway to save (ProjectsBindingSource.Current, DataRowView) as a variable in a Sub and use in a different Sub? Basically a variable that can be shared by 2 Subs.

    Private Sub AddNew_btn_Click(sender As Object, e As EventArgs) Handles AddNew_btn.Click
    
    row = CType(ProjectsBindingSource.Current, DataRowView).Row
    
    End Sub
    Private Sub save_btn_Click(sender As Object, e As EventArgs) Handles save_btn.Click
    
    row.SetField("Job_Status", "On Hold")
    row.SetField("Production_Status", "Processing")
    
    End Sub

    This will only end up being a mess unless you check the RowState which is really best done with DataTable events.

    https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/handling-datatable-events


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Sunday, May 5, 2019 12:28 PM
    Moderator