Fragensteller
[VS2005] Problem mit DGV und Eingabeverhalten einer CB-Cell

Frage
-
Hi Leute,
noch etwas neu in .Net und auch noch recht unerfahren mit dem
Überschreiben vorgegebener Komponenten, suche ich nach guten Quellen,
die mir helfen können das gezielte Überschreiben von Basiskomponenten
und deren Funktionsweisen zu lernen.Bei Recherchen im Netz bin ich auf unterschiedliche kommerzielle
Angebote gestoßen (aka Fertiglösungen), die ich aber vorweg erstmal
ausschließen möchte. Mein Ziel ist es das selbst zu tun und daran auch
zu lernen. So schwierig kann das im Einzelfall ja nicht sein.Ein erster Versuch mit Hilfe einer Quelle im Web ist zum Glück
gelungen. Speziell geht es bei meinem zweiten Versuch darum, einer
ComboBoxCell eines DGV abzugewöhnen, nur Listform zu sein, sondern
auch Eingabefeld (DropDownStyle=DropDown). Das ist mir sogar gelungen.
Dummerweise geht danach nur nix. Die Eingabe geht bei Return verloren,
es findet keine Übernahme in die Zelle statt und der Focus geht in die
nächste Zeile anstatt sinnigerweise in das nächste freie Feld der
selben Zeile. Ich verstehe auch zugegebenermaßen die innere
Architektur dieses DGV nicht ganz. Vielleicht kann mir da ja ein
erfahrener Komponentencoder mal auf die Sprünge helfen. (Bei zu
umfangreichen und für die ganze Gruppe nicht mehr interessanten oder
zu banalen Beschreibungen auch gerne per direkter PN.)Quellcodes, die ich mit Google gesucht haben, haben mir bisher zu
diesem Thema nichts gebracht. Teils waren sie veraltet (VB6), teils
waren sie schlicht falsch und funktionierten nicht, teils waren sie so
schlecht kommentiert, dass ich Wochen bräuchte mich da hineinzulesen.Vielleicht kann mir einer von euch da helfen.
LG, Dennis.
EDIT 1: Ich sehe gerade, dass ein Christian Tauschek das selbe Problem hatte, und offenbar mit ihm angebotenen Quellcodes von Peter Götz nicht zum Ziel kam. Mir geht das genauso. Auf die Quellcodes bin ich natürlich auch schon gestoßen. Aber wie bei ihm handelt es sich bei mir um ein DGV und nicht das DG. Und was Peter damals mit einem "eben eine eigene DGVComboBoxColumn selber schreiben" bezeichnet, bereitet mir eben arge Probleme. Offenbar Christian ebenso. Der Thread endet jedenfalls nicht so, als wären alle fragen beantwortet. Vielleicht hat er es allerdings inzwischen gelöst ... an der Lösung wäre ich dann sehr interessiert. :-)
Alle Antworten
-
Hallo,
Ein erster Versuch mit Hilfe einer Quelle im Web ist zum Glück
gelungen. Speziell geht es bei meinem zweiten Versuch darum,
einer ComboBoxCell eines DGV abzugewöhnen, nur Listform
zu sein, sondern auch Eingabefeld (DropDownStyle=DropDown).
Das ist mir sogar gelungen.Ich rate mal, dass es Dir gelungen ist, die ComboBox im DGV
sichtbar zu machen. Dass diese dann auch mit allen ihren
möglichen Funktionalitäten korrekt arbeitet, bezweifle ich ein
wenig.Dummerweise geht danach nur nix.
Die Eingabe geht bei Return verloren,
es findet keine Übernahme in die Zelle stattDazu musst Du natürlich entpsrechenden Code schreiben.
und der Focus geht in die nächste Zeile anstatt sinnigerweise
in das nächste freie Feld der selben Zeile.Das ist ein leider wenig praxisnahes Standardverhalten des
DataGridView, das man ändern sollte und ändern kann.
Unterwww.gssg.de -> Visual Basic -> VB.net
-> DataGridView
-> DataGridView Sort/Unsortgibt es ein Beispiel mit einem entspr. angepassten DGV.
Ich verstehe auch zugegebenermaßen die innere
Architektur dieses DGV nicht ganz. Vielleicht kann mir da ja ein
erfahrener Komponentencoder mal auf die Sprünge helfen. (Bei zu
umfangreichen und für die ganze Gruppe nicht mehr interessanten
oder zu banalen Beschreibungen auch gerne per direkter PN.)Mit der ComboBoxColumn, die eine echte ComboBox mit allen
DropDownStyles, also auch mit DropDownStyle = DropDown
hast Du Dir ein reichlich kompexes Control vorgenommen, das
nicht nur mit simplen Texten (wie eine TextBox in einer TextboxColumn),
sondern auch mit komplexen Objekten arbeiten kann und das
macht die Sache eben auch deutlich umfangreicher und leider
auch unübersichtlicher.Ich bin gerade dabei eine DGVComboBoxColumn zu schreiben.
Ist aber leider noch nicht fertig und wird wg. des doch nicht
ganz geringen Umfanges noch eine Weile dauern.
EDIT 1: Ich sehe gerade, dass ein Christian Tauschek das selbe
Problem hatte, und offenbar mit ihm angebotenen Quellcodes von
Peter Götz nicht zum Ziel kam.Es gibt auf meiner Internetpräsenz (www.gssg.de) ein Beispiel
für eine ComboBoxColumn (mit allen DropDownStyles) für das
ältere DataGrid.
Du könntest also dieses Beispiel nutzen. Da das DataGrid
die selbe Optik wie das DGV bietet und auch viaDG.DataSource = Datenquelle
gebunden werden kann wäre das eine sehr wohl praktikable
Lösung.Mir geht das genauso. Auf die Quellcodes bin ich natürlich auch
schon gestoßen. Aber wie bei ihm handelt es sich bei mir um ein
DGV und nicht das DG.Was spricht denn gegen die Verwendung des DataGrid anstatt
des DataGridView?Und was Peter damals mit einem "eben eine eigene
DGVComboBoxColumn selber schreiben" bezeichnet, bereitet
mir eben arge Probleme.Nicht nur Dir. ;-)
Offenbar Christian ebenso. Der Thread endet jedenfalls nicht so,
als wären alle fragen beantwortet. Vielleicht hat er es allerdings
inzwischen gelöst ... an der Lösung wäre ich dann sehr interessiert. :-)Wie schon erwähnt, arbeite ich gerade an einer solchen "Lösung".
Gerade mit der ComboBox gibt es vieles mehr zu beachten, als
beim in vieler Hinsicht einfacheren CalendarControl.
Bis zu meiner fertigen Lösung wird es deshalb noch eine Weile
dauern.In vielen Fällen ist es möglich das DataGridView ohne oder zumindest
ohne grosse Codeänderungen durch ein DataGrid und umgekehrt ein
DataGrid durch ein DataGridView zu ersetzen.
Du müsstest also mal konkretisieren, warum Du kein DataGrid
verwenden möchtest bzw. kannst.Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen) -
Hallo vbbedi,
bitte verwende deinen Realnamen. Ich habe zufällig gelesen, dass auch ich in deinem Posting vorkomme. Ja ich hatte das Problem mit der ComboBoxColumn, welches ich aber nun gelöst habe. Siehe untenstehender Code. Einiges davon kommt von Peter. Beachte aber die Sub "OnSelectedIndexChanged" bei der ComboBox in der Class ComboBoxAutoCompleteEditingControl.
Diese ist nämlich notwendig, damit der Wert auch im Fall von DropDownStyle = DropDownList übernommen wird.
Damit ein Wert auch nach drücken von Return übernommen werden kann, dann sieh dir die Function ProcessCmdKey an: (zB.: bei einem CalendarControl)Untenstehend drei Codeblöcke, die so ziemlich alle deine Probleme lösen dürften. Und das alles mit einem DataGridView ohne das alte DataGrid verwenden zu müssen.
mfg
Christian Tauschek''''''''''''''''''''''''''''''''''''''''''''''''''''''''Beginn Block 1''''''''''''''''''''''''''''''''''''''''''''''''''
#Region
"Klassen, die es ermglichen ein Kalender Steuerelement innerhalb eines DataGridView zu verwenden"
Public Class DataGridViewCalendarColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New CalendarCell)
End Sub
"Properties"
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If (value IsNot Nothing) AndAlso _
Not value.GetType().IsAssignableFrom(GetType(CalendarCell)) _
Then
Throw New InvalidCastException("Must be a CalendarCell")
End If
MyBase.CellTemplate = value
End Set
End Property
Region
End Class
Public Class CalendarCell
Inherits DataGridViewTextBoxCell
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim ctl As CalendarEditingControl = _
CType(DataGridView.EditingControl, CalendarEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing Or TypeOf (Me.Value) Is DBNull) Then
ctl.Value = CType(DateTime.Now, DateTime) 'das heutige Datum
Else
ctl.Value = CType(Me.Value, DateTime)
End If
End Sub
"Properties"
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that CalendarCell uses.
Return GetType(CalendarEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that CalendarCell contains.
Return GetType(DateTime)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
Return Nothing 'standardmig ist in der Zelle kein Datum eingetragen
End Get
End Property
Region
End Class
Class CalendarEditingControl
Inherits DateTimePicker
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
Me.Format = DateTimePickerFormat.Short
End Sub
Public Function GetEditingControlFormattedValue(ByVal context _
As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Value.ToShortDateString()
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As _
DataGridViewCellStyle) _
Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.CalendarForeColor = dataGridViewCellStyle.ForeColor
Me.CalendarMonthBackground = dataGridViewCellStyle.BackColor
End Sub
Public Function EditingControlWantsInputKey(ByVal key As Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
' Let the DateTimePicker handle the keys listed.
Select Case key And Keys.KeyCode
Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _
Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp
Return True
Case Else
Return Not dataGridViewWantsInputKey
End Select
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
' No preparation needs to be done.
End Sub
Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
'wenn die 'Enter' - Taste gedrckt wurde, dann wird der angezeigte Datumswert bernommen
If keyData = Keys.Return Then
Date.TryParse(Me.Text, Me.Value)
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
"Properties"
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.Value.ToShortDateString()
End Get
Set(ByVal value As Object)
Try
' This will throw an exception of the string is
' null, empty, or not in the format of a date.
Me.Value = DateTime.Parse(CStr(value))
Catch
' In the case of an exception, just use the default
' value so we're not left with a null value.
Me.Value = DateTime.Now
End Try
End Set
End Property
Public Property EditingControlRowIndex() As Integer _
Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public ReadOnly Property RepositionEditingControlOnValueChange() _
As Boolean Implements _
IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView _
Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean _
Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor _
Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Region
End Class
Region
#End
#End
#Region
#End
#Region
#End
#Region
''''''''''''''''''''''''''''''''''''''''''''''''''''''''Beginn Block 2''''''''''''''''''''''''''''''''''''''''''''''''''
#Region "Funktionen, damit beim Drücken der Enter-Taste nach rechts und nicht nach unten gesprungen wird" ' gsDataGridView ist vom DataGridView abgeleitet ' ' gsDataGridView hat gegenüber dem normalen DataGridView ' ein verändertes Verhalten beim Drücken der Eingabetaste. ' ' DataGridView wechselt beim Drücken der Eingabetaste ' in die erstejeweils darunterliegende Zeile/Zelle, ' diese Verhalten ist wenig praxisgerecht. ' ' gsDataGridView wechselt beim Drücken der Eingabetaste ' in die nächste, rechts daneben liegende Zelle der selben ' Zeile und erst beim Drücken der Eingabetaste in der ' letzten (rechten) Zelle einer Zeile zur ersten (linken) ' sichtbaren, nicht schreibgeschützten Zelle der nächsten ' Zeile. Sind alle Spalten schreibgeschützt, wird zu letzten ' sichtbaren Spalte der nächsten Zeile gewechselt. ' ' Alle übrigen Funktionalitäten entsprechen dem normalen ' DatagridView. Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean ' Prüfen ob Eingabetaste gedrückt wurde If (keyData And Keys.KeyCode) = Keys.Enter Then ' Eingabe an ProcessRightKey umleiten Return Me.ProcessRightKey(keyData) End If ' Normale Ereignisbehandlung für alle übrigen Tasten Return MyBase.ProcessDialogKey(keyData) End Function Private Shadows Function ProcessRightKey(ByVal keyData As Keys) As Boolean ' Prüfen, ob es sich um die umgeleitete Eingabetaste handelt. If (keyData And Keys.KeyCode) = Keys.Enter Then Dim DGVC As DataGridViewCell = MyBase.CurrentCell ' DGVC is Nothing kann vorkommen, wenn für alle ' Spalten .Columns.Visible = False gesetzt ist. If DGVC IsNot Nothing Then Dim RowIndex As Integer = MyBase.Rows(MyBase.CurrentCell.RowIndex).Index Dim ColIndex As Integer = MyBase.CurrentCell.ColumnIndex Dim LastVisibleCol As Integer = -1 Dim NewColIndex As Integer = -1 ' NewColIndex ermitteln Dim i As Integer Do While NewColIndex < 0 For i = (ColIndex + 1) To (MyBase.Columns.Count - 1) If MyBase.Rows(RowIndex).Cells(i).Visible Then LastVisibleCol = i If MyBase.Rows(RowIndex).Cells(i).ReadOnly = False Then NewColIndex = i Exit Do End If End If Next ' Wenn im ersen Durchlauf der for-Schleife ' keine nicht schreibgeschützte ' Zelle gefunden wurde, in der ' nächsten Zeile weitersuchen. If NewColIndex < 0 Then RowIndex = RowIndex + 1 ColIndex = 0 End If If RowIndex > (MyBase.Rows.Count - 1) Then Exit Do End If Loop If RowIndex < MyBase.Rows.Count Then Try MyBase.CurrentCell = MyBase.Rows(RowIndex).Cells(NewColIndex) Catch ex As Exception 'diese Try-Catch musste ich einfügen, da in bestimmten Umständen die obige Routine zu einem Fehler führt 'warum das so ist weiß ich nicht End Try Return True End If End If End If ' Normale Ereignisbehandlung, wenn ' nicht die Eingabetaste gedrückt war Return MyBase.ProcessRightKey(keyData) End Function Protected Overrides Function ProcessDataGridViewKey(ByVal e As System.Windows.Forms.KeyEventArgs) As Boolean ' Prüfen, ob Taste Enter gedrückt wurde If e.KeyCode = Keys.Enter Then ' Umleiten an ProcessRightKey Return Me.ProcessRightKey(e.KeyData) End If ' Normale Ereignisbehandlung, wenn ' nicht die Eingabetaste gedrückt war Return MyBase.ProcessDataGridViewKey(e) End Function #End Region
''''''''''''''''''''''''''''''''''''''''''''''''''''''''Beginn Block 3''''''''''''''''''''''''''''''''''''''''''''''''''
#Region "Klassen, die es ermöglichen ein ComboBoxAutoComplete Steuerelement innerhalb eines DataGridView zu verwenden" 'eine ComboBox, die eine Vorschlagsliste während des Eingebens anzeigt Public Class ComboBoxAutoComplete Inherits ComboBox Public Sub New() With Me .AutoCompleteSource = AutoCompleteSource.ListItems .AutoCompleteMode = AutoCompleteMode.Suggest End With End Sub #Region "Properties" Public Property DataGridViewComboBoxAutoCompleteParameters() As DataGridViewComboBoxAutoCompleteParameters Get Dim DGVCBACP As New DataGridViewComboBoxAutoCompleteParameters With DGVCBACP .MaxInputLength = Me.MaxLength .DataSource = Me.DataSource .ValueMember = Me.ValueMember .DropDownStyle = Me.DropDownStyle End With Return DGVCBACP End Get Set(ByVal value As DataGridViewComboBoxAutoCompleteParameters) With Me Me.MaxLength = value.MaxInputLength Me.DataSource = value.DataSource Me.ValueMember = value.ValueMember Me.DropDownStyle = value.DropDownStyle End With End Set End Property #End Region End Class 'die Spalte, die eine ComboBoxAutoComplete enthält Public Class DataGridViewComboBoxAutoCompleteColumn Inherits DataGridViewColumn 'beim Anlegen der ComboBoxAutoCompleteCell werden gleich die Einstellungen der ComboBox verwendet Public Sub New(ByVal DataGridViewComboBoxAutoCompleteParameters As DataGridViewComboBoxAutoCompleteParameters) Dim CBACC As New ComboBoxAutoCompleteCell CBACC.Tag = DataGridViewComboBoxAutoCompleteParameters 'im TAG der Zellen-Vorlage werden alle Parameter einschließlich der Auflistung für die DataGridViewComboBoxAutoComplete übergeben MyBase.CellTemplate = CBACC End Sub #Region "Properties" Public Overrides Property CellTemplate() As DataGridViewCell Get Return MyBase.CellTemplate End Get Set(ByVal value As DataGridViewCell) ' Ensure that the cell used for the template is a ComboBoxAutoCompleteCell. If (value IsNot Nothing) AndAlso _ Not value.GetType().IsAssignableFrom(GetType(ComboBoxAutoCompleteCell)) _ Then Throw New InvalidCastException("Must be a ComboBoxAutoCompleteCell") End If MyBase.CellTemplate = value End Set End Property #End Region End Class Public Class ComboBoxAutoCompleteCell Inherits DataGridViewTextBoxCell 'diese Sub wird aufgerufen, wenn die Zelle editiert wird und dadurch muss die ComboBox initialisiert und angezeigt werden Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As DataGridViewCellStyle) ' Set the value of the editing control to the current cell value. MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle) With CType(DataGridView.EditingControl, ComboBoxAutoCompleteEditingControl) 'Einstellungen für die anzuzeigende ComboBox übergeben .DataGridViewComboBoxAutoCompleteParameters = CType(Me.Tag, DataGridViewComboBoxAutoCompleteParameters) Dim ACSC As New AutoCompleteStringCollection For Each r As DataRow In CType(.DataGridViewComboBoxAutoCompleteParameters.DataSource, DataView).Table.Rows ACSC.Add(CStr(r(.DataGridViewComboBoxAutoCompleteParameters.ValueMember))) Next ' AutoComplete-Auflistung für ComboBox .AutoCompleteCustomSource = ACSC ' Use the default row value when Value property is null. If (Me.Value Is Nothing Or TypeOf (Me.Value) Is DBNull) Then .Text = String.Empty Else .Text = CType(Me.Value, String) End If End With End Sub #Region "Properties" Public Overrides ReadOnly Property EditType() As Type Get ' Return the type of the editing control that ComboBoxAutoCompleteCell uses. Return GetType(ComboBoxAutoCompleteEditingControl) End Get End Property Public Overrides ReadOnly Property ValueType() As Type Get ' Return the type of the value that ComboBoxAutoCompleteCell contains. Return GetType(String) End Get End Property Public Overrides ReadOnly Property DefaultNewRowValue() As Object Get ' Use the current String as the default value. Return String.Empty End Get End Property #End Region End Class Class ComboBoxAutoCompleteEditingControl Inherits ComboBoxAutoComplete Implements IDataGridViewEditingControl Private dataGridViewControl As DataGridView Private valueIsChanged As Boolean = False Private rowIndexNum As Integer Public Function GetEditingControlFormattedValue(ByVal context _ As DataGridViewDataErrorContexts) As Object _ Implements IDataGridViewEditingControl.GetEditingControlFormattedValue Return Me.Text End Function Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As _ DataGridViewCellStyle) _ Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl Me.Font = dataGridViewCellStyle.Font Me.ForeColor = dataGridViewCellStyle.ForeColor Me.BackColor = dataGridViewCellStyle.BackColor End Sub Public Function EditingControlWantsInputKey(ByVal key As Keys, _ ByVal dataGridViewWantsInputKey As Boolean) As Boolean _ Implements IDataGridViewEditingControl.EditingControlWantsInputKey ' Let the ComboBoxAutoComplete handle the keys listed. Select Case key And Keys.KeyCode Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _ Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp Return True Case Else Return Not dataGridViewWantsInputKey End Select End Function Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _ Implements IDataGridViewEditingControl.PrepareEditingControlForEdit ' No preparation needs to be done. End Sub Protected Overrides Sub OnTextChanged(ByVal eventargs As EventArgs) ' Notify the DataGridView that the contents of the cell have changed. valueIsChanged = True Me.EditingControlDataGridView.NotifyCurrentCellDirty(True) MyBase.OnTextChanged(eventargs) End Sub Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs) 'diese Sub ist notwendig, da ansonsten der Cell-Wert nicht übernommen wird, wenn die ComboBox auf DropDownStyle = DropDownList eingestellt ist valueIsChanged = True Me.EditingControlDataGridView.NotifyCurrentCellDirty(True) MyBase.OnSelectedIndexChanged(e) End Sub #Region "Properties" Public ReadOnly Property RepositionEditingControlOnValueChange() _ As Boolean Implements _ IDataGridViewEditingControl.RepositionEditingControlOnValueChange Get Return False End Get End Property Public Property EditingControlFormattedValue() As Object _ Implements IDataGridViewEditingControl.EditingControlFormattedValue Get Return Me.Text End Get Set(ByVal value As Object) Me.Text = CStr(value) End Set End Property Public Property EditingControlRowIndex() As Integer _ Implements IDataGridViewEditingControl.EditingControlRowIndex Get Return rowIndexNum End Get Set(ByVal value As Integer) rowIndexNum = value End Set End Property Public Property EditingControlDataGridView() As DataGridView _ Implements IDataGridViewEditingControl.EditingControlDataGridView Get Return dataGridViewControl End Get Set(ByVal value As DataGridView) dataGridViewControl = value End Set End Property Public Property EditingControlValueChanged() As Boolean _ Implements IDataGridViewEditingControl.EditingControlValueChanged Get Return valueIsChanged End Get Set(ByVal value As Boolean) valueIsChanged = value End Set End Property Public ReadOnly Property EditingControlCursor() As Cursor _ Implements IDataGridViewEditingControl.EditingPanelCursor Get Return MyBase.Cursor End Get End Property #End Region End Class 'hier werden die Werte zum Einstellen der ComboBox übergeben Public Class DataGridViewComboBoxAutoCompleteParameters Private _MaxInputLength As Integer 'der Wert der maximalen Eingabelänge wird allen ComboBoxAutoCompleteCell - Klassen zur Verfügung gestellt Private _DataSource As Object 'die Datenquelle für die ComboBox wird jeder ComboBox zur Verfügung gestellt Private _ValueMember As String 'das ist der Name der Spalte, die die ComboBox in der Auflistung anzeigen soll Private _DropDownStyle As ComboBoxStyle = ComboBoxStyle.DropDown 'der DropDownStyle (zB.: DropDown als Default) #Region "Properties" 'hier wird die maximal mögliche Eingabelänge festgelegt Public Property MaxInputLength() As Integer Get Return _MaxInputLength End Get Set(ByVal value As Integer) _MaxInputLength = value End Set End Property 'die Datenquelle für die Auflistung in der ComboBox Public Property DataSource() As Object Get Return _DataSource End Get Set(ByVal value As Object) _DataSource = value End Set End Property 'der Name der Spalte, die die ComboBox in der Auflistung anzeigen soll Public Property ValueMember() As String Get Return _ValueMember End Get Set(ByVal value As String) _ValueMember = value End Set End Property 'der DropDownStyle (zB.: DropDownList) Public Property DropDownStyle() As ComboBoxStyle Get Return _DropDownStyle End Get Set(ByVal value As ComboBoxStyle) _DropDownStyle = value End Set End Property #End Region End Class #End Region
-
Erstmal danke für deine Codeblöcke, Christian.
Ich habe sie eben eingebaut, und teste nun damit herum. Was mir auffällt:
- Ein Fehler tritt auf, wenn das DGV noch ohne Zeilen ist (also nur mit NEW erstellt und dann eine Spalte deiner AutoCompleteColumn eingefügt). Dieser Fehler (NullReferenceException) tritt auf bei:
For Each r As DataRow In CType(.DataGridViewComboBoxAutoCompleteParameters.DataSource, DataView).Table.Rows
ACSC.Add(
CStr(r(.DataGridViewComboBoxAutoCompleteParameters.ValueMember)))
Next
- Was mir noch nicht ganz klar ist: wo binde ich die drei Key-Routinen aus Block 2 ein? Im Hauptcode?
- Der erste Block macht mich etwas stutzig, denn beim Einbinden rief der zig Fehler hervor. Ich weiss nicht, woran das gerade liegt, aber da er auch eher die CalenderCell behandelt, lass ich den mal fürs erste beiseite.
Die anderen Teile aus Block 3 (zumindest die, an denen ich gerade herumteste) habe ich ausgelagert in eine neue Klassendatei. Denke mal, so war das auch gedacht. Ich lager sowas immer gerne aus, in externe Dateien, damit ich es leicht in anderen Programmen erneut einbinden kann.
Ich teste mal weiter, bis später ...
LG, Dennis.
-
Also das klappt irgendwie noch nicht ... ich habe jetzt mal ein kleines Testprogramm geschrieben, das so eine Spalte erstellt:
Dim MyPars As New DataGridViewComboBoxAutoCompleteParameters
Dim CB As New ComboBox
CB.Items.Clear()
CB.Items.Add(
"Meins")
CB.Items.Add(
"Deins")
CB.Items.Add(
"Unsers")
MyPars.DropDownStyle = ComboBoxStyle.DropDown
MyPars.DataSource = CB.DataSource
MyPars.MaxInputLength = -1
MyPars.ValueMember =
""
Dim NewCol As New DataGridViewComboBoxAutoCompleteColumn(MyPars)
MyDGV.Columns.Add(NewCol)
MyDGV.AllowUserToAddRows =
False
MyDGV.AllowUserToDeleteRows =
False
MyDGV.AllowUserToOrderColumns =
True
MyDGV.Rows.Add(
"Test")
Die Zeile Test scheint auch. Aber wenn ich daraufklicke kommt eine NullRefException. In der oben bereits geposteten Zeile mit dem "For Each r as DataRow" ...
Hab ich da irgendwas entscheidendes übersehen? Was ich auch noch nicht ganz schnalle ist, wie du die Parameter im Tag übergibst. Denn für mich sieht es so aus, als kämen dort gar keine Parameter an ...
Vielleicht kannst du mir nochmal auf die Sprünge helfen. :-)
LG, Dennis.