Hallo Community!
Ich habe meinen geschlossenen Beitrag Nach erfolgter Auswahl die Auswahlliste in einer DataGridViewComboBox ändern wieder 'aufgemacht'.
Mich hat dieses damalige Vorhaben wieder aus Interesse und Neugier gepackt und habe versucht weiterzumachen.
Der Beitrag Items Collection Property erstellen von Demmy hat mich zu neuen Ideen verleitet.
Mein damaliges Problem:
Eine ComboBox in einer DataGridView anzuwenden, die ihre Listeneinträge um den jeweils ausgewählten Eintrag reduziert,
damit nur ein Wert der Auswahlliste in einer Spalte vorkommen kann.
Ich hatte es damals mit einer ComboBoxColumn versucht und damit nur DGV-Ausnahmen,
wie "Der DataGridViewComboBoxCell-Wert ist ungültig" produziert.
Des Weiteren konnte ich nur eine Spalte im DGV bedienen und hatte auch keine richtige Datenanbindung...
Spoiler anzeigen
Wer Interesse hat, kann oben im Expander Auszüge von den 3 Klassen durchstöbern und unten
das vollständiges Demo herunterladen, das den derzeitigen Status (lauffähig) zeigt.
Hier kann man in der Entwurfszeit bei den benutzerdefinierten Einstellungen
(Datasource, Datamember, Valuemember bzw. Items-Auflistung und ComboBox-Styles)
im Aufgaben-Propertyfenster (bei Spalten bearbeiten) herumspielen ...
Die eingebauten Extensions stammen vom ErfinderDesRades
Ich wäre sehr dankbar für Tipp's und Trick's zum Code etc.
mfg
VB1963
Ich habe meinen geschlossenen Beitrag Nach erfolgter Auswahl die Auswahlliste in einer DataGridViewComboBox ändern wieder 'aufgemacht'.
Mich hat dieses damalige Vorhaben wieder aus Interesse und Neugier gepackt und habe versucht weiterzumachen.
Der Beitrag Items Collection Property erstellen von Demmy hat mich zu neuen Ideen verleitet.
Mein damaliges Problem:
Eine ComboBox in einer DataGridView anzuwenden, die ihre Listeneinträge um den jeweils ausgewählten Eintrag reduziert,
damit nur ein Wert der Auswahlliste in einer Spalte vorkommen kann.
Ich hatte es damals mit einer ComboBoxColumn versucht und damit nur DGV-Ausnahmen,
wie "Der DataGridViewComboBoxCell-Wert ist ungültig" produziert.
Des Weiteren konnte ich nur eine Spalte im DGV bedienen und hatte auch keine richtige Datenanbindung...
VB.NET-Quellcode
- Imports System
- Imports System.ComponentModel
- Imports System.Drawing.Design
- <Localizable(True)> _
- Public Class DepressComboBoxListColumn : Inherits DataGridViewColumn
- Private _DataSource As Object
- Private _ValueMember As String
- Private _DisplayMember As String
- Private _Items As New List(Of String)
- Public Sub New()
- MyBase.New(New DepressComboBoxListCell())
- End Sub
- ''' <summary>
- ''' Mit der Clone-Methode wird erreicht,
- ''' dass schlussendlich der Form-Desiner
- ''' die Daten vom Eigenschaftsfenster übernimmt!!!
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Overrides Function Clone() As Object
- Dim col As DepressComboBoxListColumn = DirectCast(MyBase.Clone(), DepressComboBoxListColumn)
- col.CellTemplate = DirectCast(Me.CellTemplate.Clone(), DepressComboBoxListCell)
- col.Items = Me.Items
- col.DataSource = Me.DataSource
- col.DisplayMember = Me.DisplayMember
- col.ValueMember = Me.ValueMember
- col.DropDownStyle = Me.DropDownStyle
- col.FlatStyle = Me.FlatStyle
- Return col
- End Function
- <Browsable(False)> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
- Public Overrides Property CellTemplate() As DataGridViewCell
- Get
- Return MyBase.CellTemplate
- End Get
- Set(value As DataGridViewCell)
- If (value IsNot Nothing) AndAlso Not (TypeOf value Is DepressComboBoxListCell) Then
- Throw New ArgumentException("DataGridView: falscher Typ von CellTemplate, es muss eine DepressComboBoxListCell sein")
- End If
- MyBase.CellTemplate = value
- End Set
- End Property
- #Region "ComboBoxStyle"
- Private _DropDownStyle As ComboBoxStyle
- <Category("Darstellung")> _
- <Description("Steuert die Darstellung und Funktionalität der Combobox.")> _
- <ReadOnlyAttribute(False)> _
- <DefaultValue(ComboBoxStyle.DropDown)> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
- <RefreshProperties(RefreshProperties.Repaint)> _
- Public Property DropDownStyle() As ComboBoxStyle
- Get
- If _DropDownStyle = ComboBoxStyle.Simple Then _DropDownStyle = ComboBoxStyle.DropDown
- Return _DropDownStyle
- End Get
- Set(value As ComboBoxStyle)
- _DropDownStyle = value
- End Set
- End Property
- Private _FlatStyle As FlatStyle
- <Category("Darstellung")> _
- <Description("Bestimmt die Anzeige der Combobox.")> _
- <ReadOnlyAttribute(False)> _
- <DefaultValue(FlatStyle.Standard)> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
- <RefreshProperties(RefreshProperties.Repaint)> _
- Public Property FlatStyle() As FlatStyle
- Get
- Return _FlatStyle
- End Get
- Set(value As FlatStyle)
- _FlatStyle = value
- End Set
- End Property
- #End Region
- #Region "Datenherkunft"
- <Category("Data")> _
- <Description("Die Datenquelle, die die Auswahl für die Kombinationsfelder auffüllt.")> _
- <DefaultValue(DirectCast(Nothing, String))> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
- <RefreshProperties(RefreshProperties.All)> _
- <Localizable(False)> _
- <MergableProperty(False)> _
- <TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a")> _
- <AttributeProvider(GetType(IListSource))> _
- Public Property DataSource() As Object
- Get
- Return _DataSource
- End Get
- Set(value As Object)
- If value IsNot Nothing AndAlso Not (TypeOf value Is IList OrElse TypeOf value Is IListSource) Then
- Throw New Exception("Die angegebene DataSource ist für eine komplexe Datenbindung ungeeignet")
- Else
- If _DataSource IsNot value Then
- _DataSource = value
- Me.Items.Clear()
- If IsNothing(value) Then
- Me.ValueMember = String.Empty
- Me.DisplayMember = String.Empty
- End If
- End If
- End If
- End Set
- End Property
- <Category("Data")> _
- <Description("Eine Zeichenfolge, die die Eigenschaft oder Spalte angibt, " & _
- "von der Zeichenfolgen für die Anzeige in den Kombinationsfeldern abgerufen werden.")> _
- <DefaultValue(DirectCast(Nothing, String))> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
- <RefreshProperties(RefreshProperties.All)> _
- <Localizable(False)> _
- <MergableProperty(False)> _
- <TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a")> _
- <Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a", _
- GetType(System.Drawing.Design.UITypeEditor))> _
- Public Property DisplayMember() As String
- Get
- Return _DisplayMember
- End Get
- Set(value As String)
- If _DisplayMember <> value Then _DisplayMember = value
- End Set
- End Property
- <Category("Data")> _
- <Description("Eine Zeichenfolge, die die Eigenschaft oder Spalte angibt, " & _
- "aus der Werte abgerufen werden, die der Auswahl in der Dropdownliste entsprechen.")> _
- <DefaultValue(DirectCast(Nothing, String))> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _
- <RefreshProperties(RefreshProperties.All)> _
- <Localizable(False)> _
- <MergableProperty(False)> _
- <TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a")> _
- <Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a", _
- GetType(System.Drawing.Design.UITypeEditor))> _
- Public Property ValueMember() As String
- Get
- Return _ValueMember
- End Get
- Set(value As String)
- If _ValueMember <> value Then _ValueMember = value
- End Set
- End Property
- <Category("Data")> _
- <Description("Eine Auflistung der Objekte, die in den Kombinationsfeldern " & _
- "als Auswahl verwendet werden.")> _
- <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
- <Localizable(False)> _
- <MergableProperty(False)> _
- <Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, " & _
- "System.Design, " & _
- "Version=4.0.0.0, " & _
- "Culture=neutral, " & _
- "PublicKeyToken=b03f5f7f11d50a3a",
- GetType(System.Drawing.Design.UITypeEditor))> _
- Public Property Items As List(Of String)
- Get
- Return _Items
- End Get
- Set(value As List(Of String))
- If IsNothing(Me.DataSource) Then _Items = value
- End Set
- End Property
- #End Region
- End Class 'DepressComboBoxListColumn
- Public Class DepressComboBoxListCell : Inherits DataGridViewTextBoxCell
- Public Sub New()
- Me.Style.Format = String.Empty
- End Sub
- Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
- ByVal initialFormattedValue As Object, _
- ByVal dataGridViewCellStyle As DataGridViewCellStyle)
- ' den Wert des Bearbeitungsteuerelementes auf den aktuellen Zellwert setzen.
- MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
- '
- Dim ctl As DepressComboBoxListEditingControl =
- CType(Me.DataGridView.EditingControl, DepressComboBoxListEditingControl)
- If Not String.IsNullOrEmpty(initialFormattedValue.ToString) Then ctl.Text = initialFormattedValue.ToString
- ctl.DropDownStyle = CType(Me.OwningColumn, DepressComboBoxListColumn).DropDownStyle
- ctl.FlatStyle = CType(Me.OwningColumn, DepressComboBoxListColumn).FlatStyle
- '
- 'Liste dynamisch befüllen!
- If Not fillComboBoxList(ctl) Then Throw New ArgumentException("Datenauswertungsfehler in der ComboBoxListe")
- End Sub
- Public Overrides ReadOnly Property EditType() As Type
- ' Typ des Bearbeitungssteuerelementes vom DepressComboBoxListCell
- Get
- Return GetType(DepressComboBoxListEditingControl)
- End Get
- End Property
- Public Overrides ReadOnly Property ValueType() As Type
- Get
- Return GetType(String) ' Wertetyp vom DepressComboBoxListCell
- End Get
- End Property
- Public Overrides ReadOnly Property DefaultNewRowValue() As Object
- Get
- Return String.Empty
- End Get
- End Property
- Private Function fillComboBoxList(cbx As DepressComboBoxListEditingControl) As Boolean
- Dim col = TryCast(Me.OwningColumn, DepressComboBoxListColumn)
- If IsNothing(col) Then Return False ' Fehler im TryCast-DepressComboBoxListColum
- Dim colIndex = col.Index 'Bezugsspalte Index feststellen
- Dim colName = col.DataPropertyName 'Bezugsspalte DataPropertyName feststellen
- If String.IsNullOrEmpty(colName) Then Return False 'Fehler
- '
- Dim externList As New List(Of String)
- If IsNothing(col.DataSource) Then
- externList = col.Items
- Else
- If String.IsNullOrEmpty(col.ValueMember) Then Return False
- Dim bsData = DirectCast(col.DataSource, BindingSource)
- If IsNothing(bsData) Then Return False
- Dim dvData As DataView = TryCast(bsData.List, DataView)
- If IsNothing(dvData) Then Return False
- If col.ValueType IsNot dvData.Table.Columns(col.ValueMember).DataType Then Return False 'ungleiche Datentypen
- dvData.Table.AcceptChanges() 'alle zwischenzeitlich gemachten Änderungen an der Tabelle durchführen.
- For r = 0 To dvData.Table.Rows.Count - 1
- externList.Add(dvData.Table.Rows(r)(col.ValueMember).ToString)
- Next
- End If
- '
- externList.Sort()
- cbx.Items.Clear() 'ComboBoxListe leeren
- Dim bs = TryCast(Me.DataGridView.DataSource, BindingSource)
- If IsNothing(bs) Then Return False ' Fehler bei BindingSource-Cast
- Dim dv = TryCast(bs.List, DataView)
- If IsNothing(dv) Then Return False ' Fehler bei DataView-Cast
- For Each i In externList 'externe Liste abgleichen
- If Not String.IsNullOrEmpty(i) Then
- If Not findValue(dv, colName, i) Then cbx.Items.Add(i)
- End If
- Next
- clearDuplicate(cbx)
- Return True
- End Function
- Private Function findValue(dv As DataView, colName As String, v As String) As Boolean
- For row = 0 To dv.Table.Rows.Count - 1
- If v = dv.Table.Rows(row)(colName).ToString Then Return True
- Next
- Return False
- End Function
- Private Sub clearDuplicate(ByVal cbx As DepressComboBoxListEditingControl)
- If cbx.Items.Count <= 1 Then Return
- For i = cbx.Items.Count - 1 To 0 Step -1
- Dim e = cbx.Items(i).ToString
- For j = 0 To i - 1
- If e = cbx.Items(j).ToString Then cbx.Items.Remove(e)
- Next
- Next
- End Sub
- End Class ' DepressComboBoxListCell
- Class DepressComboBoxListEditingControl : Inherits ComboBox
- 'Definiert gemeinsame Funktionen für Steuerelemente, die sich innerhalb von Zellen einer DataGridView befinden.
- Implements IDataGridViewEditingControl
- '
- 'Dieser Teil ist wegen Überlänge des Beitrages im Dateianhang anzusehen
- '
- End Class 'DepressComboBoxListEditingControl
Wer Interesse hat, kann oben im Expander Auszüge von den 3 Klassen durchstöbern und unten
das vollständiges Demo herunterladen, das den derzeitigen Status (lauffähig) zeigt.
Hier kann man in der Entwurfszeit bei den benutzerdefinierten Einstellungen
(Datasource, Datamember, Valuemember bzw. Items-Auflistung und ComboBox-Styles)
im Aufgaben-Propertyfenster (bei Spalten bearbeiten) herumspielen ...
Die eingebauten Extensions stammen vom ErfinderDesRades
Ich wäre sehr dankbar für Tipp's und Trick's zum Code etc.
mfg
VB1963
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VB1963“ ()