2017-05-26 1 views
0

Ich habe einen Teil meines Codes, der eine Registerkarte in einer Tabsteuerung erstellt, und füllt sie dann mit einer Datagridview, die ein paar Spalten enthält, die DataGridViewComboBoxColumn sind.VB.NET Wie Ereignis-Handler zu ComboBoxColumn in programmgesteuerten Steuerelementen hinzugefügt?

Es sieht wie folgt aus:

Private Sub NewTabPage() 
    Dim TabPageCount As Integer = RacerOrderTAB.TabPages.Count 
    RacerOrderTAB.TabPages.Add(TeamNames(TabPageCount)) 'teamnames() is an array of team names 

    Dim CurrentTabPage = RacerOrderTAB.TabPages(TabPageCount) 
    Dim GridToAdd As New DataGridView 

    GridToAdd.Size = CurrentTabPage.Size 
    GridToAdd.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill 
    GridToAdd.Location = New Point(CurrentTabPage.Location.X, CurrentTabPage.Location.Y) 
    GridToAdd.Columns.Add("ShiftCOL", "Shift Name") 
    GridToAdd.Name = "grid_" & CurrentTabPage.Text 

    For y As Integer = 1 To ShiftSetup.racerspershift 'add extra column for each racer in shift 

     Dim cmb As New DataGridViewComboBoxColumn 

     cmb.HeaderText = "Racer" & y 
     cmb.Name = "Racer_" & y 
     cmb.MaxDropDownItems = AmountOfRacers 
     cmb.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton 

     GridToAdd.Columns.Add(cmb) 
    Next 

    RacerOrderTAB.TabPages(TabPageCount).Controls.Add(GridToAdd) 
End Sub 

Aber ich habe für die Comboboxen in das Hinzufügen eines Eventhandler Schwierigkeiten gehabt. Was ich möchte ist, dass wenn eine Combobox angeklickt und geöffnet wird, ich sie mit den gewünschten Elementen bevölkere. Ich schaffte es vage, um es Arbeit durch Zugabe:

AddHandler GridToAdd.EditingControlShowing, AddressOf <sub name> 

aber dann nicht in der Lage gewesen, um herauszufinden, welche Combobox geklickt wurde, und wie sie zu füllen. Es hat auch wie vier Klicks erfordert, bevor die Drop-Liste erscheint. Ich bin nur leicht verwirrt.

Danke für jeden Hinweis; Diese DataGridViewComboBoxColumns [tiefer Atem] haben mich sehr verwirrt!

+0

Es gibt normalerweise keine 'ComboBox'-Steuerelemente in der Spalte und nie mehr als eins, so dass es nie erforderlich ist, zu bestimmen, auf welches geklickt wurde. Im Event-Handler 'EditingControlShowing' kann über die Eigenschaft 'e.Control' auf die einzige' ComboBox' zugegriffen werden. – jmcilhinney

+0

Es ist unklar, was die Kombinationsfelder enthalten sollen. Der gebuchte Code scheint zahlreiche Kombinationsfeldspalten zu erstellen. Es gibt jedoch im verbuchten Code keine Elemente, die diesen Kombinationsfeldern Elemente hinzufügen. Können Sie klären, was die Kombinationsfelder enthalten sollen? Entweder haben sie alle die gleichen Werte oder jeder hat seine eigenen Werte, aber der Code tut dies auch nicht. – JohnG

+0

@JohnG Die Idee war, dass ich gesendet werden würde, welche Combobox der Benutzer klickte, und ich konnte es dann zur Laufzeit auffüllen. –

Antwort

1

Es kann ein wenig hacky sein, aber es sollte tun, was Sie fragen ... hoffentlich. Ich habe zwei List(Of String) Variablen erstellt. AllRacers enthält alle Rennfahrer ... d. H. Alle Namen, die in einem Kombinationsfeld angezeigt werden sollen, so dass kein anderes Kombinationsfeld in dieser Reihe ein Element ausgewählt hat. Diese Namen werden alle Kombinationsfelder in allen Zeilen ursprünglich in der Liste auswählbarer Elemente enthalten. Die andere List(Of String)UsedRacers enthält eine Liste aller "Comboboxen" in der aktuellen Zeile, die Elemente ausgewählt haben. Jedes Mal, wenn ein Zellenwert geändert wird und es sich um eine der "combobox" -Spaltenzellen handelt, wird UsedRacers gelöscht/aktualisiert, um das hinzugefügte/geänderte ausgewählte Element in der aktuellen Zeile widerzuspiegeln.

Wenn ein „comboBox“ Zellwert geändert wird, SetUsedRacersForRow genannt ...

Private Sub SetUsedRacersForRow(rowIndex As Int16) 
    UsedRacers.Clear() 
    Dim curValue = "" 
    For i = 1 To racersPerShift 
    If (Not (dgvRacers.Rows(rowIndex).Cells(i).Value Is Nothing)) Then 
     curValue = dgvRacers.Rows(rowIndex).Cells(i).Value.ToString() 
     If (Not (String.IsNullOrEmpty(curValue))) Then 
     UsedRacers.Add(curValue) 
     End If 
    End If 
    Next 
End Sub 

Der obigen Code einer Schleife durch alle „Combobox“ Zellen in der gegebenen Reihe und wenn eine „Combobox“ Zelle etwas ausgewählt hat Der ausgewählte Wert wird zur Liste UsedRacers hinzugefügt.

Jetzt, da die ausgewählten Elemente für alle "Comboboxen" in dieser Zeile in der UsedRacers Liste sind, können wir nun jede "Combobox" -Zelle in dieser Zeile durchlaufen und die richtige Liste von Namen festlegen. Um zu helfen, wird eine Methode erstellt, die DataGridViewComboBoxCell zurückgibt, so dass die Namen in der aktuellen UsedRacers Liste NICHT in der DataGridViewComboBoxCell Liste der auswählbaren Namen sind.

Das einzige Problem hier wäre mit Zellen, die derzeit ein Element ausgewählt haben. Für jede "Combobox" -Zelle mit einem ausgewählten Objekt muss der ausgewählte Eintrag eindeutig in der Liste der Elemente enthalten sein. Um dies zu beheben, muss überprüft werden, ob die Zelle "combobox" einen Wert enthält. Enthält die "combobox" -Zelle einen ausgewählten Wert, dann ist dieser Wert auch in der UsedRacers-Liste enthalten. Da DIESE Zelle die Zelle ist, die in der UseRacers Liste ist ... müssen wir diesen Wert zu dieser Zellenelementliste HINZUFÜGEN. Andernfalls könnten wir die eindeutige Auswahl nicht anzeigen.

Um die UsedRacers Liste konsistent zu halten, müssen wir dieses Element direkt zu der einzelnen "Combobox" -Zelle hinzufügen und nicht die UsedRacers Liste entfernen oder ändern, da dies für die anderen "Combobox" -Zellen verwendet wird.Mit anderen Worten ... welcher Wert in einem Kombinationsfeld ausgewählt wird, wir müssen sicherstellen, dass es sich um eines der Elemente in der Liste der auswählbaren Elemente der "Combobox" handelt. Ich hoffe das ergibt Sinn.

Dies kann alles im DataGridViewsCellChanged Ereignis getan werden.

Private Sub dgvRacers_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvRacers.CellValueChanged 
    If (e.ColumnIndex >= 1 And e.ColumnIndex <= racersPerShift) Then 
    SetUsedRacersForRow(e.RowIndex) 
    For i = 1 To racersPerShift 
     Dim newCell As DataGridViewComboBoxCell = GetCurrentComboBoxCell() 
     If (Not (dgvRacers.Rows(e.RowIndex).Cells(i).Value Is Nothing)) Then 
     Dim curValue = dgvRacers.Rows(e.RowIndex).Cells(i).Value.ToString() 
     newCell.Items.Add(curValue) 
     newCell.Value = curValue 
     End If 
     dgvRacers.Rows(e.RowIndex).Cells(i) = newCell 
    Next 
    End If 
End Sub 

In dem obigen Code wird ein Verfahren GetCurrentComboBoxCell (unten) ein DataGridViewComboBoxCell so gibt, dass die Elemente in der Combo-Boxen Liste der Elemente keine Elemente enthalten, die in der UsedRacers Liste enthalten sind. Aus diesem Grund ist eine Überprüfung erforderlich (siehe oben), um festzustellen, ob die Zelle bereits einen Wert enthält. HINWEIS: Die zurückgegebene DataGridViewComboBoxCell enthält immer ein "leeres" leeres Element. Dies ist erforderlich, um dem Benutzer zu ermöglichen, einen aktuell ausgewählten Wert zu "deaktivieren" und dann den "De-Selected" -Element für die anderen Kombinationsfeldzellen verfügbar zu machen.

Public Function GetCurrentComboBoxCell() As DataGridViewComboBoxCell 
    Dim newComboCell = New DataGridViewComboBoxCell() 
    newComboCell.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton 
    newComboCell.FlatStyle = FlatStyle.Flat 
    newComboCell.Items.Add("") 
    For Each curRacer In AllRacers 
    If (Not UsedRacers.Contains(curRacer)) Then 
     newComboCell.Items.Add(curRacer) 
    End If 
    Next 
    Return newComboCell 
End Function 

Schließlich all diese Zusammenstellung ...

Dim racersInShift = 3 
Dim AllRacers As List(Of String) = New List(Of String) From {"John", "Bobby", "Trent", "Josh", "Chapman", "Henry", "George", "Marvin"} 
'Dim racersPerShift As Int16 = AllRacers.Count '<-- should be MAX value 
Dim racersPerShift As Int16 = 4 
Dim UsedRacers = New List(Of String) 

Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    BuildGrid() 
End Sub 

Private Sub BuildGrid() 
    dgvRacers.Size = New Size(800, 200) 
    dgvRacers.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill 
    'dgvRacers.Location = New Point(50, 200) 
    dgvRacers.Columns.Add("ShiftCOL", "Shift Name") 
    dgvRacers.Name = "RacersDGV" 
    dgvRacers.EditMode = DataGridViewEditMode.EditOnEnter 
    dgvRacers.AllowUserToAddRows = False 
    AddRacerColumns() 
    AddRacerRows() 
End Sub 

Private Sub AddRacerColumns() 
    Dim newColumn As DataGridViewComboBoxColumn 
    For i As Integer = 1 To racersPerShift 
    newColumn = GetNewComboBoxColumn("Racer" & i, "Racer " & i) 
    dgvRacers.Columns.Add(newColumn) 
    Next 
End Sub 

Private Sub AddRacerRows() 
    For i As Integer = 1 To racersInShift 
    Dim row As New DataGridViewRow 
    dgvRacers.Rows.Add(row) 
    Next 
End Sub 

Private Sub dgvRacers_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) 
    ‘See code above 
End Sub 

Private Sub SetUsedRacersForRow(rowIndex As Int16) 
    ‘See code above 
End Sub 

Public Function GetCurrentComboBoxCell() As DataGridViewComboBoxCell 
    ‘See code above 
End Function 

‘Lastly a method to set a whole `DataGridviewComboBoxColumn` which is used to initialize all the combo box columns 

Public Function GetNewComboBoxColumn(colName As String, colHeader As String) As DataGridViewComboBoxColumn 
    Dim newComboCol = New DataGridViewComboBoxColumn() 
    newComboCol.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton 
    newComboCol.FlatStyle = FlatStyle.Flat 
    newComboCol.Items.Add("") 
    newComboCol.HeaderText = colHeader 
    newComboCol.Name = colName 
    For Each curRacer In AllRacers 
    newComboCol.Items.Add(curRacer) 
    Next 
    Return newComboCol 
End Function 

Ich hoffe, das hilft, ich vermute es einen einfacheren Weg, dies zu tun ist.

Verwandte Themen