Bound DataGridView not updating to display information + sorting issues

后端 未结 2 1457
情话喂你
情话喂你 2021-01-24 04:36

I have a bound DataGridView1 and several bound TextBoxes and DateTimePickers.

Everything is working well, except when I try to accomplish these two things in conjunction

相关标签:
2条回答
  • 2021-01-24 05:15

    DGV shows edited value after cell validation and this seems to be an issue around DGV. In order to do that (considered as workaround) you can simulate/force by yourself your grid validation (calling the method below) after you have setted the value on your cell:

    Private Sub SimulateDGVValidation()
    
        Try
    
            Dim currentCell As DataGridViewCell = Me.DataGridView1.CurrentCell
    
            If (currentCell) IsNot Nothing Then
                Dim c As Integer = IIf(currentCell.ColumnIndex > 1, currentCell.ColumnIndex - 1, 1)
                Me.DataGridView1.CurrentCell = Me.DataGridView1(c, currentCell.RowIndex)
            Else
                Me.DataGridView1.CurrentCell = Me.DataGridView1(0, 0)
            End If
    
    
            Application.DoEvents()
    
            'Return in the initial cell 
            If (currentCell) IsNot Nothing Then
                Me.DataGridView1.CurrentCell = currentCell
            End If
    
    
        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try
    
    End Sub
    
    0 讨论(0)
  • 2021-01-24 05:19

    Since the BindingSource data source can be sorted, use the BindingSource.Sort property instead of sorting the control (your DataGridView). columnName is the name of the Column used for sorting (you can specify more than one Column):

    myBindingSource.Sort = $"{columnName} ASC"
    

    Then, when the User sets the DateTimePicker.Value, update the Cell value, corresponding to DateTime Column of the current Row, using the ValueChanged event:

    Method 1: Bound DateTimePicker

    In the DateTimePicker.ValueChanged, the BindingSource.EndEdit() method is called, to apply immediately the new value to the data source.

    Note 1: for this method to work as expected, the BindingSource data source must be a DataTable or another container that implements the IEditableObject interface.

    DateTimePicker1.DataBindings.Add(
        New Binding("Value", myBindingSource, "MyDateTimeColumn", False, DataSourceUpdateMode.OnValidation))
    
    '(...)
    
    Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
        myBindingSource.EndEdit()
    End Sub
    

    Note 2: the DateTimePicker doesn't support a null/DbNull value. If the DataSouce may contain DBNull values, it may become erratic. You'll probably need to create a custom control from it, to manage its behavior. Otherwise, see Method 2

    Method 2: UnBound DateTimePicker

    The userSetValue field is used when setting the DateTimePicker value in code, to prevent the procedure in the ValueChanged event to update the DateTime Columns's Value. This way, the event will only update the Column when a User changes the date manually.

    Private columnName As String = String.Empty
    Private userSetValue As Boolean = True
    
    Private Sub DateTimePicker1_ValueChanged(sender As Object, e As EventArgs) Handles DateTimePicker1.ValueChanged
        If (Not userSetValue) Then Return
        If (DataGridView1.CurrentRow Is Nothing) OrElse
            (DataGridView1.CurrentRow.Cells($"{columnName}").ValueType IsNot GetType(Date)) Then Return
    
        'DataGridView1.SuspendLayout()
        DataGridView1.CurrentRow.Cells($"{columnName}").Value = DateTimePicker1.Value
        myBindingSource.EndEdit()
        'DataGridView1.ResumeLayout(False)
    End Sub
    

    ► Test both methods with and without SuspendLayout() / ResumeLayout().

    The RowPostPaint event (for example) can be used to update the DateTimePicker.Value the associated Columns' value:

    Private Sub DataGridView1_RowPostPaint(sender As Object, e As DataGridViewRowPostPaintEventArgs) Handles DataGridView1.RowPostPaint
        userSetValue = False
        Dim currentValue = DataGridView1.CurrentRow.Cells("MyDateTimeColumn").Value
        If currentValue Is Nothing OrElse currentValue Is DBNull.Value Then currentValue = Date.Now
        DateTimePicker1.Value = DirectCast(currentValue, Date)
        userSetValue = True
    End Sub
    

    Using any of the two methods, this is the result:

    0 讨论(0)
提交回复
热议问题