Με αφορμή αυτό το thread, ξεκινάω ένα δεύτερο που έχει να κάνει με το πρόβλημα που περιγράφει ο τίτλος. Έγραψα λίγο διερευνητικό κώδικα για να διαπιστώσω κατά πόσο είναι εφικτή η βελτίωση στο user experience. Αποφάσισα να εκμεταλλευτώ το SelectedValueChanged Event του ComboBox προκειμένου να "πιέσω" το datagridview να κάνει τα updates που πρέπει στις τιμές των child cells, αφού επιλεγεί η τιμή από το combo. Δούλεψα κατευθείαν πάνω στο gridview και όχι με τα bindingsources, οπότε φαντάζομαι ότι ο κώδικας επιδέχεται βελτίωση. Έτσι όπως είναι γραμμένος φαίνεται να δουλεύει και εν μέρει με τον τρόπο αυτό προσπαθώ ν' απαντήσω στο τελευταίο ερώτημα του thread του constantine-55. Πρόκειται για επέκταση του κώδικα του solution ανέβασα στο εν λόγω thread, οπότε δεν υπάρχει λόγος να ανεβάσω νέο συνημμένο, παρά μόνο τον κώδικα της φόρμας. Περιμένω τις παρατηρήσεις σας...
Reminder: I am NOT a VB-er, so be nice...
Public Class Form1
Dim generaChildBS As New BindingSource ' Τα bindingsources που θα γίνεται το filtering...
Dim speciesChildBS As New BindingSource
Private Sub FlowerColourBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FlowerColourBindingNavigatorSaveItem.Click
Try
Me.Validate()
Me.FlowerColourBindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.TaxonomyDataSet)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.FamiliesTableAdapter.Fill(Me.TaxonomyDataSet.Families)
Me.GeneraTableAdapter.Fill(Me.TaxonomyDataSet.Genera)
Me.SpeciesTableAdapter.Fill(Me.TaxonomyDataSet.Species)
Me.FlowerColourTableAdapter.Fill(Me.TaxonomyDataSet.FlowerColour)
'
generaChildBS.DataSource = Me.TaxonomyDataSet
generaChildBS.DataMember = "Genera"
'
speciesChildBS.DataSource = Me.TaxonomyDataSet
speciesChildBS.DataMember = "Species"
End Sub
Private Sub FlowerColourDataGridView_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles FlowerColourDataGridView.EditingControlShowing
If Me.FlowerColourDataGridView.CurrentCell.ColumnIndex = FamilyCombo.Index Then
Dim control = CType(e.Control, DataGridViewComboBoxEditingControl)
AddHandler control.SelectedValueChanged, AddressOf FamilyCombo_SelectedValueChanged
ElseIf Me.FlowerColourDataGridView.CurrentCell.ColumnIndex = GenusCombo.Index Then
Dim control = CType(e.Control, DataGridViewComboBoxEditingControl)
control.DataSource = Me.generaChildBS
'
Me.FilterGeneraChildBindingSource()
'
' Όταν εμφανιστεί το combo, και στο κελί υπάρχει ήδη τιμή, πρέπει η επιλεγμένη τιμή στο combo
' να είναι ίδια με εκείνη του κελιού
If Not String.IsNullOrEmpty(Me.FlowerColourDataGridView.CurrentCell.Value.ToString()) Then
control.SelectedValue = Me.FlowerColourDataGridView.CurrentCell.Value
End If
'
AddHandler control.SelectedValueChanged, AddressOf GenusCombo_SelectedValueChanged ' Ο event handler πρέπει να προστεθεί ύστερα από το SelectedValue "assignement"
ElseIf Me.FlowerColourDataGridView.CurrentCell.ColumnIndex = SpeciesCombo.Index Then
Dim control = CType(e.Control, DataGridViewComboBoxEditingControl)
control.DataSource = Me.speciesChildBS
'
Me.FilterSpeciesChildBindingSource()
'
If Not String.IsNullOrEmpty(Me.FlowerColourDataGridView.CurrentCell.Value.ToString()) Then
control.SelectedValue = Me.FlowerColourDataGridView.CurrentCell.Value
End If
'
AddHandler control.SelectedValueChanged, AddressOf SpeciesCombo_SelectedValueChanged ' Ο event handler πρέπει να προστεθεί ύστερα από το SelectedValue "assignement"
End If
End Sub
Private Sub FamilyCombo_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim control = CType(sender, DataGridViewComboBoxEditingControl)
Dim dgv = CType(control.Parent.Parent, DataGridView)
'
Dim currentFamilyValue = CType(Me.FlowerColourBindingSource.Current, DataRowView)("Family").ToString()
If control.SelectedValue IsNot Nothing Then
Dim selectedFamilyValue = control.SelectedValue.ToString()
If (currentFamilyValue <> selectedFamilyValue) Then
Me.FlowerColourDataGridView.CurrentCell.Value = selectedFamilyValue
End If
End If
'
RemoveHandler control.SelectedValueChanged, AddressOf FamilyCombo_SelectedValueChanged
End Sub
Private Sub GenusCombo_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim control = CType(sender, DataGridViewComboBoxEditingControl)
Dim dgv = CType(control.Parent.Parent, DataGridView)
'
Dim currentGenusValue = CType(Me.FlowerColourBindingSource.Current, DataRowView)("Genus").ToString()
If control.SelectedValue IsNot Nothing Then
Dim selectedGenusValue = control.SelectedValue.ToString()
If (currentGenusValue <> selectedGenusValue) Then
Me.FlowerColourDataGridView.CurrentCell.Value = selectedGenusValue
End If
End If
'
RemoveHandler control.SelectedValueChanged, AddressOf GenusCombo_SelectedValueChanged
End Sub
Private Sub SpeciesCombo_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim control = CType(sender, DataGridViewComboBoxEditingControl)
Dim dgv = CType(control.Parent.Parent, DataGridView)
'
Dim currentSpeciesValue = CType(Me.FlowerColourBindingSource.Current, DataRowView)("Species").ToString()
If control.SelectedValue IsNot Nothing Then
Dim selectedSpeciesValue = control.SelectedValue.ToString()
If (currentSpeciesValue <> selectedSpeciesValue) Then
Me.FlowerColourDataGridView.CurrentCell.Value = selectedSpeciesValue
End If
End If
'
RemoveHandler control.SelectedValueChanged, AddressOf SpeciesCombo_SelectedValueChanged
End Sub
Private Sub FilterGeneraChildBindingSource()
'Dim familyName = Me.FlowerColourDataGridView.Rows(Me.FlowerColourDataGridView.CurrentCell.RowIndex).Cells(FamilyCombo.Index).Value.ToString()
'
Dim familyName = CType(Me.FlowerColourBindingSource.Current, DataRowView)("Family").ToString()
If Not String.IsNullOrEmpty(familyName) Then
Dim familyRow = CType(Me.FamiliesBindingSource.Item(Me.FamiliesBindingSource.Find("FamilyName", familyName)), DataRowView)
Dim familyID = CType(familyRow("FamilyID"), Short)
generaChildBS.Filter = "FamilyID=" + familyID.ToString()
Else
generaChildBS.Filter = "FamilyID=-1" ' Εάν δεν έχει επιλεγεί οικογένεια, τότε η λίστα των γενών πρέπει να είναι κενή
End If
End Sub
Private Sub FilterSpeciesChildBindingSource()
'Dim genusName = Me.FlowerColourDataGridView.Rows(Me.FlowerColourDataGridView.CurrentCell.RowIndex).Cells(GenusCombo.Index).Value.ToString()
'
Dim genusName = CType(Me.FlowerColourBindingSource.Current, DataRowView)("Genus").ToString()
If Not String.IsNullOrEmpty(genusName) Then
speciesChildBS.Filter = "Genus='" + genusName + "'"
Else
speciesChildBS.Filter = "Genus=''" ' Εάν δεν έχει επιλεγεί γένος, τότε η λίστα των ειδών πρέπει να είναι κενή
End If
End Sub
Private Sub FlowerColourDataGridView_DataError(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles FlowerColourDataGridView.DataError
MessageBox.Show(e.Exception.Message)
e.Cancel = True
End Sub
Private Sub FlowerColourDataGridView_CellValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles FlowerColourDataGridView.CellValueChanged
'
' Όπως σου είπα πιο πάνω, πιο σωστό όπου μπορείς να επεμβαίνεις κατευθείαν στο bindingsource και
' όχι στο grid. Για το λόγο αυτό, δοκίμασε να "παίξεις" με το "CurrentItemChanged" event του FlowerColourBindingSource,
' αντί του "CellValueChanged" event του FlowerColourDataGridView...
'
If e.RowIndex <> Me.FlowerColourDataGridView.NewRowIndex Then
If e.ColumnIndex = FamilyCombo.Index Then
Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.GenusCombo.Index).Value = DBNull.Value
ElseIf e.ColumnIndex = GenusCombo.Index Then
Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.SpeciesCombo.Index).Value = DBNull.Value
ElseIf e.ColumnIndex = SpeciesCombo.Index Then
Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.FlowerColourTextBox.Index).Value = DBNull.Value
End If
'
' Στο παρόν παράδειγμα έκανα τις στήλες του DataTable Nullable. Αν δεν είναι και στη βάση, τότε
' είναι σχεδόν βέβαιο ότι θα φας exception. Οπότε πιο λογικό είναι κάθε φορά που αλλάζει η
' τιμή ενός κελιού σε μεγαλύτερο επίπεδο, τα μικρότερα να παίρνουν μια default τιμή...
'
'If e.ColumnIndex = FamilyCombo.Index Then
' Me.FilterGeneraChildBindingSource()
' Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.GenusCombo.Index).Value = CType(Me.generaChildBS(0), DataRowView)("Genus").ToString()
'ElseIf e.ColumnIndex = GenusCombo.Index Then
' Me.FilterSpeciesChildBindingSource()
' Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.SpeciesCombo.Index).Value = CType(Me.speciesChildBS(0), DataRowView)("Species").ToString()
'ElseIf e.ColumnIndex = SpeciesCombo.Index Then
' Me.FlowerColourDataGridView.Rows(e.RowIndex).Cells(Me.FlowerColourTextBox.Index).Value = "New colour"
'End If
End If
End Sub
Private Sub btnReloadData_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReloadData.Click
Me.FlowerColourTableAdapter.Fill(Me.TaxonomyDataSet.FlowerColour)
End Sub
End Class
Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!