Ecrire dans une DataGridViewComboBoxColumn
J'ai une datagridview avec une DataGridViewComboBoxColumn.
Les items de la DataGridViewComboBoxColumn sont alimentés par le code et non bindés à une bd. Je ne parviens pas à donner la possibilité à l'utilisateur d'écrire dans cette DataGridViewComboBoxColumn qui est dispo pour les combobox classique. Est ce possible ?
Quelle pourrait être une alternative?
Merci de m'éclairer.
AllowWritingDGVCBColumn version béta !
Yop !
Voilà le code.
C'est moyen mais bon ça marche pas trop mal.
Il s'agit donc d'une classe héritée du datagridviewcomboboxcolumn qui permet la saisie de valeurs non dans la source et qui entraîne la maj de la base dans la foulée --> donc le datasource de la column doit être un dataadaptater basé sur une requête qui rend une seule colonne (cf. exemple). C'est logique car dans ma version plus complexe, je dois en absence de l'item dans la liste débrancher sur un formulaire spécifique de création de l'item et ça complique de beaucoup le code.
Mais bon, ça aide à comprendre le principe...
ATTENTION : C'est du vite fait je garantis pas l'absence de bugs !
Donc les classes pour la colonne :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
Option Strict On
Option Explicit On
Imports System
Imports System.Data.OleDb
#Region "AllowWritingDGVCB"
'
' Colonne de type liste avec chargement dynamique
'
Public Class AllowWritingDGVCBEditingControl
Inherits DataGridViewComboBoxEditingControl
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private cColumn As AllowWritingDGVCBColumn
Friend WriteOnly Property Column() As AllowWritingDGVCBColumn
Set(ByVal value As AllowWritingDGVCBColumn)
cColumn = value
End Set
End Property
Protected Overrides Sub OnTextChanged( _
ByVal e As EventArgs)
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
End Sub
Protected Overrides Sub OnPreviewKeyDown( _
ByVal e As PreviewKeyDownEventArgs)
If e.KeyCode = Keys.Tab Or e.KeyCode = Keys.Enter Then
Me.OnLeave(New EventArgs)
End If
End Sub
Protected Overrides Sub OnLeave( _
ByVal e As EventArgs)
ChekValue()
MyBase.OnLeave(e)
End Sub
Protected Sub ChekValue()
'
' Gestion du chargement dynamique
'
Dim dtTable As DataTable = CType(Me.DataSource, DataTable)
Dim dvTable As New DataView(dtTable)
dvTable.RowFilter = dtTable.Columns(0).ColumnName & "='" & Me.Text & "'"
' La valeur est trouvée dans la source --> rien a faire
If dvTable.Count > 0 Then Exit Sub
' La valeur n'est pas trouvée dans la source --> on l'insére
'
Dim strText As String = Me.Text
cColumn.AddNewSourceItem(strText)
' Ruse a 20 centimes car l'update provoque le rechargement de la liste
' et le changement de la valeur éditée.
' Ceci provoque un appel réentrant mais j'ai pas mieux pour l'instant !
' --> piste = remove du handler sur changement de text ?
Me.Text = strText
End Sub
Public Overrides Function EditingControlWantsInputKey(ByVal key As Keys, _
ByVal dataGridViewWantsInputKey As Boolean) As Boolean
Select Case key And Keys.KeyCode
Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _
Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp, _
Keys.Enter, Keys.Tab
Return True
Case Else
Return False
End Select
End Function
End Class
Public Class AllowWritingDGVCBColumn
Inherits DataGridViewComboBoxColumn
Private daListe As OleDbDataAdapter
Private cbListe As OleDbCommandBuilder
Private dsListe As New DataSet
Private myCnn As New OleDbConnection
Private bsListe As New BindingSource
Public Sub New()
MyBase.New()
MyBase.CellTemplate = New AllowWritingDGVCBCell
End Sub
Public Overloads WriteOnly Property DataSource() As Object
Set(ByVal value As Object)
If Not TypeOf (value) Is OleDbDataAdapter Then
MsgBox("Erreur le datasource doit etre un OleDbDataAdapter ")
Exit Property
End If
daListe = CType(value, OleDbDataAdapter)
cbListe = New OleDbCommandBuilder(daListe)
daListe.Fill(dsListe)
Me.ValueMember = dsListe.Tables(0).Columns(0).ColumnName
Me.DisplayMember = dsListe.Tables(0).Columns(0).ColumnName
MyBase.DataSource = dsListe.Tables(0)
End Set
End Property
Friend Sub AddNewSourceItem(ByVal value As String)
dsListe.Tables(0).Rows.Add(value)
daListe.Update(dsListe)
End Sub
End Class
Public Class AllowWritingDGVCBCell
Inherits DataGridViewComboBoxCell
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
ByVal initialFormattedValue As Object, _
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, _
dataGridViewCellStyle)
Dim col As AllowWritingDGVCBColumn = _
CType(MyBase.DataGridView.Columns(MyBase.ColumnIndex), AllowWritingDGVCBColumn)
Dim ctl As AllowWritingDGVCBEditingControl = _
CType(DataGridView.EditingControl, AllowWritingDGVCBEditingControl)
ctl.DropDownStyle = ComboBoxStyle.DropDown
ctl.AutoCompleteMode = AutoCompleteMode.None
ctl.Column = CType(Me.DataGridView.Columns(Me.ColumnIndex), AllowWritingDGVCBColumn)
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
Return GetType(AllowWritingDGVCBEditingControl)
End Get
End Property
End Class
#End Region |
Et un formulaire de test Form4 avec un datagridview Datagridview1 :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
Option Strict On
Option Explicit On
Imports System
Imports System.Data.OleDb
Public Class Form4
Private daListe As OleDbDataAdapter
Private myCnn As New OleDbConnection
Private Sub Form4_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
' Connexion à la base
myCnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=""C:\Add\Add\Suivi Projet\Suivi Projet AF.mdb"""
myCnn.Open()
'
' Création de l'adaptateur pour alim du datasource de la colonne
'
Dim strSqlQuery As String = "SELECT col1 FROM Table1"
Try
' adaptateur pour la base de donnée
daListe = New OleDbDataAdapter(New OleDb.OleDbCommand(strSqlQuery, myCnn))
Catch ex As Exception
MsgBox("Ca alors ! Une erreur : " & ex.Message)
End Try
' Crée la colonne dans le datagridview
Dim c As New AllowWritingDGVCBColumn
c.DataSource = daListe
Me.DataGridView1.Columns.Add(c)
End Sub
End Class |
J'espére faire avancer le chmilblick !
Cdt.