Cette classe permet de mettre n'importe quel contrôle dans le mode édition de la datagrid et de choisir le type de donnée de la colonne.
La propriété Value ou Text (si Value pas trouvée) de ce contrôle contient automatiquement la valeur de la cellule de la datagrid
Dernière Maj: Correction de la gestion du Null (encore)
- Prise en compte d'une propriété de valeur minimale pour le control de saisi
ex: Le datetimepicker possède une propriété DateMin, si les valeurs sont inférieurs à cette propriété, ca casse. Il suffit d'indiquer le nom de cette propriété dans le constructeurs pour que ca fonctionne (attention à la casse du nom de la propriété)
Source / Exemple :
Public Class DataGridControlColumn
Inherits System.Windows.Forms.DataGridColumnStyle
#Region "Variables"
Private _xMargin As Integer = 2
Private _yMargin As Integer = 1
Private _Control As System.Windows.Forms.Control
Private _OldVal As String = String.Empty
Private _InEdit As Boolean = False
Public InnerControlType As Type
Public ColumnDataType As Type
Public MinimumValuePropertyName As String
#End Region
#Region "Constructeurs"
Public Sub New(ByVal TypeOfInnerControl As Type, ByVal MappingName As String, ByVal ColumnDataType As Type, ByVal Alignement As System.Windows.Forms.HorizontalAlignment, ByVal HeaderText As String, ByVal NullText As String, ByVal Width As Int32, Optional ByVal MinimumValuePropertyName As String = "")
MyClass.New(TypeOfInnerControl, MappingName, ColumnDataType, MinimumValuePropertyName)
MyBase.Alignment = Alignement
MyBase.HeaderText = HeaderText
MyBase.MappingName = MappingName
MyBase.NullText = NullText
MyBase.Width = Width
End Sub
Public Sub New(ByVal TypeOfInnerControl As Type, ByVal MappingName As String, ByVal ColumnDataType As Type, Optional ByVal MinimumValuePropertyName As String = "")
MyClass.ColumnDataType = ColumnDataType
MyClass.InnerControlType = TypeOfInnerControl
MyBase.MappingName = MappingName
MyClass._Control = Activator.CreateInstance(Me.InnerControlType)
MyClass._Control.Visible = False
MyClass.MinimumValuePropertyName = MinimumValuePropertyName
End Sub
#End Region
Public Property InnerControl() As System.Windows.Forms.Control
Get
Return MyClass._Control
End Get
Set(ByVal Value As System.Windows.Forms.Control)
MyClass._Control = Value
End Set
End Property
#Region "Heritage de DataGridColumnStyle"
Protected Overloads Overrides Sub Abort(ByVal RowNum As Integer)
MyClass.RollBack()
MyClass.HideForm()
MyClass.EndEdit()
End Sub
Protected Overloads Overrides Function Commit(ByVal DataSource As System.Windows.Forms.CurrencyManager, ByVal RowNum As Integer) As Boolean
Try
MyClass.HideForm()
If Not MyClass._InEdit Then Return True
Dim Value As Object
Dim Prop As Reflection.PropertyInfo = MyClass._Control.GetType.GetProperty("Value")
If Prop Is Nothing Then
Value = MyClass._Control.Text
Else
Value = Prop.GetValue(MyClass._Control, Nothing)
End If
If NullText.Equals(MyClass.GetText(Value)) Then
Value = System.DBNull.Value
MyBase.SetColumnValueAtRow(DataSource, RowNum, MyClass.NullText)
Else
Value = Convert.ChangeType(Value, MyClass.ColumnDataType)
If Value.GetType Is MyClass.ColumnDataType Then
MyBase.SetColumnValueAtRow(DataSource, RowNum, Value)
Else
Return False
End If
End If
Catch e As Exception
MyClass.RollBack()
Return False
End Try
MyClass.EndEdit()
Return True
End Function
Protected Overloads Overrides Sub ConcedeFocus()
MyClass._Control.Visible = False
End Sub
Protected Overloads Overrides Sub Edit(ByVal Source As System.Windows.Forms.CurrencyManager, ByVal Rownum As Integer, ByVal Bounds As System.Drawing.Rectangle, ByVal [ReadOnly] As Boolean, ByVal InstantText As String, ByVal CellIsVisible As Boolean)
If Not InstantText Is Nothing Then
MyClass._Control.Text = InstantText
Else
MyClass._Control.Text = MyClass.GetText(MyBase.GetColumnValueAtRow(Source, Rownum))
End If
Dim OriginalBounds As System.Drawing.Rectangle = Bounds
MyClass._OldVal = MyClass._Control.Text
If CellIsVisible Then
Bounds.Offset(MyClass._xMargin, MyClass._yMargin)
Bounds.Width -= MyClass._xMargin * 2
Bounds.Height -= MyClass._yMargin
MyClass._Control.Bounds = Bounds
MyClass._Control.Visible = True
Else
MyClass._Control.Bounds = OriginalBounds
MyClass._Control.Visible = False
End If
MyClass._Control.RightToLeft = MyBase.DataGridTableStyle.DataGrid.RightToLeft
MyClass._Control.Focus()
If MyClass._Control.Visible Then
MyBase.DataGridTableStyle.DataGrid.Invalidate(OriginalBounds)
End If
MyClass._InEdit = True
End Sub
#Region "Gestion des Tailles"
Protected Overloads Overrides Function GetMinimumHeight() As Integer
Return 25 'todo MyClass._Panel.PreferredHeight + MyClass._yMargin
End Function
Protected Overloads Overrides Function GetPreferredHeight(ByVal g As System.Drawing.Graphics, ByVal Value As Object) As Integer
Dim NewLineIndex As Integer = 0
Dim NewLines As Integer = 0
Dim ValueString As String = MyClass.GetText(Value)
Do
While NewLineIndex <> -1
NewLineIndex = ValueString.IndexOf("r\n", NewLineIndex + 1)
NewLines += 1
End While
Loop
Return MyBase.FontHeight * NewLines + MyClass._yMargin
End Function
Protected Overloads Overrides Function GetPreferredSize(ByVal g As System.Drawing.Graphics, ByVal Value As Object) As System.Drawing.Size
Dim Extents As System.Drawing.Size = System.Drawing.Size.Ceiling(g.MeasureString(MyClass.GetText(Value), MyBase.DataGridTableStyle.DataGrid.Font))
Extents.Width += MyClass._xMargin * 2 + MyClass.DataGridTableGridLineWidth
Extents.Height += MyClass._yMargin
Return Extents
End Function
#End Region
#Region "Méthodes Paint"
Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal Bounds As System.Drawing.Rectangle, ByVal Source As System.Windows.Forms.CurrencyManager, ByVal RowNum As Integer)
MyClass.Paint(g, Bounds, Source, RowNum, False)
End Sub
Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal Bounds As System.Drawing.Rectangle, ByVal Source As System.Windows.Forms.CurrencyManager, ByVal RowNum As Integer, ByVal AlignToRight As Boolean)
Dim Text As String = MyClass.GetText(MyBase.GetColumnValueAtRow(Source, RowNum))
MyClass.PaintText(g, Bounds, Text, AlignToRight)
End Sub
Protected Overloads Sub Paint(ByVal g As System.Drawing.Graphics, ByVal Bounds As System.Drawing.Rectangle, ByVal Source As System.Windows.Forms.CurrencyManager, ByVal RowNum As Integer, ByVal BackBrush As System.Drawing.Brush, ByVal ForeBrush As System.Drawing.Brush, ByVal AlignToRight As Boolean)
Dim Text As String = MyClass.GetText(MyBase.GetColumnValueAtRow(Source, RowNum))
MyClass.PaintText(g, Bounds, Text, BackBrush, ForeBrush, AlignToRight)
End Sub
#End Region
Protected Overloads Overrides Sub SetDataGridInColumn(ByVal Value As System.Windows.Forms.DataGrid)
MyBase.SetDataGridInColumn(Value)
If Not (MyClass._Control.Parent Is Value) Then
If Not (MyClass._Control.Parent Is Nothing) Then
MyClass._Control.Parent.Controls.Remove(MyClass._Control)
End If
End If
If Not (Value Is Nothing) Then
'MyClass._Control.Owner = Value.FindForm
Value.Controls.Add(MyClass._Control)
End If
End Sub
Protected Overloads Overrides Sub UpdateUI(ByVal Source As System.Windows.Forms.CurrencyManager, ByVal RowNum As Integer, ByVal InstantText As String)
MyClass._Control.Text = MyClass.GetText(MyBase.GetColumnValueAtRow(Source, RowNum))
If Not (InstantText Is Nothing) Then
MyClass._Control.Text = InstantText
End If
End Sub
#End Region
#Region "Méthodes privées"
Private ReadOnly Property DataGridTableGridLineWidth() As Integer
Get
If MyBase.DataGridTableStyle.GridLineStyle = System.Windows.Forms.DataGridLineStyle.Solid Then
Return 1
Else
Return 0
End If
End Get
End Property
Private Sub EndEdit()
MyClass._InEdit = False
MyBase.Invalidate()
End Sub
Private Function GetText(ByVal Value As Object) As String
If MyClass.MinimumValuePropertyName <> String.Empty Then
Dim Prop As Reflection.PropertyInfo = MyClass._Control.GetType.GetProperty(MyClass.MinimumValuePropertyName)
If Not Prop Is Nothing Then
Dim Obj As Object = Convert.ChangeType(Prop.GetValue(MyClass._Control, Nothing), MyClass.ColumnDataType)
If Value.compareto(Obj) < 0 Then Value = Obj
End If
End If
If Value Is System.DBNull.Value Then Return NullText
If Not Value Is Nothing Then
Return Value.ToString
Else
Return NullText
End If
End Function
Private Sub HideForm()
If MyClass._Control.Focused Then
MyBase.DataGridTableStyle.DataGrid.Focus()
End If
MyClass._Control.Visible = False
End Sub
Private Sub RollBack()
MyClass._Control.Text = MyClass._OldVal
End Sub
Private Sub PaintText(ByVal g As System.Drawing.Graphics, ByVal Bounds As System.Drawing.Rectangle, ByVal Text As String, ByVal AlignToRight As Boolean)
Dim BackBrush As System.Drawing.Brush = New System.Drawing.SolidBrush(MyBase.DataGridTableStyle.BackColor)
Dim ForeBrush As System.Drawing.Brush = New System.Drawing.SolidBrush(MyBase.DataGridTableStyle.ForeColor)
MyClass.PaintText(g, Bounds, Text, BackBrush, ForeBrush, AlignToRight)
End Sub
Private Sub PaintText(ByVal g As System.Drawing.Graphics, ByVal TextBounds As System.Drawing.Rectangle, ByVal Text As String, ByVal BackBrush As System.Drawing.Brush, ByVal ForeBrush As System.Drawing.Brush, ByVal AlignToRight As Boolean)
Dim Rect As System.Drawing.Rectangle = TextBounds
Dim RectF As System.Drawing.RectangleF = System.Drawing.RectangleF.op_Implicit(Rect) ' Convert to RectangleF
Dim Format As System.Drawing.StringFormat = New System.Drawing.StringFormat()
If AlignToRight Then Format.FormatFlags = System.Drawing.StringFormatFlags.DirectionRightToLeft
Select Case Me.Alignment
Case Is = System.Windows.Forms.HorizontalAlignment.Left
Format.Alignment = System.Drawing.StringAlignment.Near
Case Is = System.Windows.Forms.HorizontalAlignment.Right
Format.Alignment = System.Drawing.StringAlignment.Far
Case Is = System.Windows.Forms.HorizontalAlignment.Center
Format.Alignment = System.Drawing.StringAlignment.Center
End Select
Format.FormatFlags = Format.FormatFlags Or System.Drawing.StringFormatFlags.NoWrap
g.FillRectangle(Brush:=BackBrush, Rect:=Rect)
Rect.Offset(0, MyClass._yMargin)
Rect.Height -= MyClass._yMargin
g.DrawString(Text, MyBase.DataGridTableStyle.DataGrid.Font, ForeBrush, RectF, Format)
Format.Dispose()
End Sub
#End Region
End Class
Conclusion :
Ce code est basé sur l'exemple de Microsoft (comme le code de strikel).
Code Modifié: Correction de la gestion de la saisie. Ajout de la possibilité de choisir le type de données avec lequel travailler. Passage de valeur par la propriété Text ou Value. Value étant prioritaire, Correction et Amélioration de la gestion des valeurs Null.
Ajout d'un zip contenant un exemple de Datagrid avec TextBox, DataTimePicker et UserControl sur un Databinding avec une collection Typée.
Pas de commentaire pour le moment (pas eu le temps)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.