Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0111: DateTimePicker im DataGridView hosten

 von 

Beschreibung

Die Standard-TextboxDatagridViewColumn kann im Form-Designer durch die hier vorgestellte TimePickerColumn ausgetauscht werden (DatagridView-Smart-Tag: "Spalten bearbeiten"). Damit ist eine sichere und komfortable Eingabe für Datum- und Zeitwerte im Grid bereitgestellt.

Schwierigkeitsgrad:

Schwierigkeitsgrad 3

Framework-Version(en):

.NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5

.NET-Version(en):

Visual Basic 2005, Visual Basic 2008

Download:

Download des Beispielprojektes [26,98 KB]

' Dieser Quellcode stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!

' Projektversion:   Visual Studio 2005
' Option Strict:    An
'
' Referenzen: 
'  - System
'  - System.Data
'  - System.Drawing
'  - System.Web.Services
'  - System.Windows.Forms
'  - System.Xml
'
' Imports: 
'  - Microsoft.VisualBasic
'  - Microsoft.VisualBasic.ControlChars
'  - System
'  - System.Collections
'  - System.Collections.Generic
'  - System.Data
'  - System.Drawing
'  - System.Diagnostics
'  - System.Windows.Forms
'

' ##############################################################################
' ######################## frmDateTimePickerColumn.vb ##########################
' ##############################################################################
Imports System.Globalization
Imports System.IO

''' <summary> 
'''  Zeigt die Auswirkungen der TimePickerColumn.Format-Property auf die 
'''  Darstellung 
''' </summary>
Public Class frmDateTimePickerColumn

    Public Sub New()
        InitializeComponent()
        ' Designer-generierten Code nachbessern
        ValueGridColumn.AllowNull = True
    End Sub

    Private Sub btApply_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles btApply.Click

        Dim newFormat As String = Me.FormatTextBox.Text
        Dim col As Integer = ValueGridColumn.Index

        ' newFormat auf die Styles aller Zellen der Column anwenden
        For row As Integer = 0 To Me.DateTimesDataGridView.RowCount - 1
            Me.DateTimesDataGridView(col, row).Style.Format = newFormat
        Next

        ' Die Vorlage auf das CellTemplate anwenden, aus der das DGV die Zellen 
        '  hinzukommender Rows generiert - wirkt sich auch aufs EditingControl
        '  aus
        Me.ValueGridColumn.CellTemplate.Style.Format = newFormat
        Me.Text = String.Format("aktuelles Format = ""{0}""", newFormat)
    End Sub

    Private Sub btShortFormats_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles btShortFormats.Click

        Call (New frmListShortFormat()).Show(Me)
    End Sub
End Class

' ##############################################################################
' ########################## frmListShortFormats.vb ############################
' ##############################################################################
Imports System.Globalization

''' <summary> Listet alle Short-Patterns zur Zeitformatierung </summary>
Public Class frmListShortFormat

    Private Sub frmListShortFormat_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles MyBase.Load

        Dim t As DateTime = Now
        ' Die TimeFormat-DataTable mit ShortPatterns, LongPatterns und 
        '  formatiertem Beispiel befüllen
        Dim DTFI As DateTimeFormatInfo = DateTimeFormatInfo.CurrentInfo
        With Me.DateTimes.TimeFormat
            .AddTimeFormatRow(Nothing, _
                DTFI.GetAllDateTimePatterns("G"c)(0), t.ToString)
            ' Jeder dieser Chars ist ein Short-Pattern zur Zeitformatierung
            For Each c As Char In "dDgGtTfFmMrRsuUyY"
                .AddTimeFormatRow(c, _
                    DTFI.GetAllDateTimePatterns(c)(0), t.ToString(c))
            Next
        End With
    End Sub

End Class
' ##############################################################################
' ############################ TimePickerColumn.vb #############################
' ##############################################################################
Imports System.Globalization
Imports System.ComponentModel

' Das Hosten eines Controls in einer einer DataGridViewColumn 
'  erfordert 3 Klassen:
'   1) Die neue DataGridViewColumn
'   2) Die Standard-Zelle dieser Column, wenn nicht editiert wird
'   3) Das Editing-Control, mit dem Zellwerte editiert werden können - muss
'       IDataGridViewEditingControl implementieren

Partial Public Class TimePickerColumn
    Inherits DataGridViewColumn

    ' DateTimePicker kann sich wunderbar auf Zeit-Format-Strings einstellen. 
    '  Probleme hat er mit den vorgefertigten Short-Patterns zur 
    '  Zeitformatierung. Daher werden diese in einem Dictionary mit ihrer 
    '  kulturabhängigen ausführlichen Schreibweise assoziiert.
    Private Shared _ShortPatterns As New Dictionary(Of String, String)()
    Private _allowNull As Boolean

    Shared Sub New()
        Dim DTFI As DateTimeFormatInfo = DateTimeFormatInfo.CurrentInfo
        ' Jeder dieser Chars ist ein Short-Pattern zur Zeitformatierung
        For Each c As Char In "dDgGtTfFmMrRsuUyY"
            _ShortPatterns.Add(c, DTFI.GetAllDateTimePatterns(c)(0))
        Next
        _ShortPatterns.Add(String.Empty, _ShortPatterns("g"))
    End Sub

    Public Sub New()
        MyBase.New(New Cell())
    End Sub

    ' Designer-Bug: Egal wie im Spalten-Designer einstellt, der generierte Code 
    '  stellt diese Property auf False. Also muss zur Form-Initialisierung 
    '  nachgebessert werden.
    Public Property AllowNull() As Boolean
        Get
            Return _allowNull
        End Get
        Set(ByVal value As Boolean)
            _allowNull = value
        End Set
    End Property

    Public Overrides Property CellTemplate() As DataGridViewCell
        Get
            Return MyBase.CellTemplate
        End Get
        Set(ByVal value As DataGridViewCell)
            If value IsNot Nothing AndAlso Not (TypeOf value Is Cell) Then
                Throw New ArgumentException(String.Concat( _
                    "Es wird versucht, ", value.GetType.Name, _
                    " als CellTemplate zuzuweisen.", Lf, _
                    "Zulässig sind nur DataGridViewCells, die von ", _
                    "TimePickerColumn geerbt sind"))
            End If
            MyBase.CellTemplate = value
        End Set
    End Property

    ' Cell-Klasse eingeschachtelt, da logisch abhängig von TimePickerColumn
    Public Class Cell
        Inherits DataGridViewTextBoxCell

        Public Overloads Overrides Sub InitializeEditingControl( _
            ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, _
            ByVal cellStyle As DataGridViewCellStyle)

            MyBase.InitializeEditingControl(rowIndex, _
                initialFormattedValue, cellStyle)
            Dim picker As EditingPicker = _
                DirectCast(Me.DataGridView.EditingControl, EditingPicker)

            If DirectCast(Me.OwningColumn, TimePickerColumn)._allowNull Then
                picker.ShowCheckBox = True
                picker.Checked = True
            End If
            If Me.Value Is Nothing OrElse Convert.IsDBNull(Me.Value) Then
                picker.Value = DateTime.Now
            Else
                picker.Value = DirectCast(Me.Value, DateTime)
            End If
        End Sub

        Public Overloads Overrides ReadOnly Property EditType() As Type
            Get
                Return GetType(EditingPicker)
            End Get
        End Property

        Public Overloads Overrides ReadOnly Property ValueType() As Type
            Get
                Return GetType(DateTime)
            End Get
        End Property

    End Class 'TimePickerColumn.Cell

    ' EditingControl-Klasse eingeschachtelt, da logisch abhängig 
    '  von TimePickerColumn
    Public Class EditingPicker
        Inherits DateTimePicker
        Implements IDataGridViewEditingControl

        Private _style As DataGridViewCellStyle

        Public Sub New()
            MyBase.Format = DateTimePickerFormat.Custom
        End Sub

        Public Sub ApplyCellStyleToEditingControl( _
            ByVal dataGridViewCellStyle As DataGridViewCellStyle) _
            Implements _
                IDataGridViewEditingControl.ApplyCellStyleToEditingControl

            _style = dataGridViewCellStyle
            Me.Font = _style.Font
            Me.CalendarForeColor = _style.ForeColor
            Me.CalendarMonthBackground = _style.BackColor
            Dim f As String = _style.Format
            Dim [Long] As String = String.Empty
            If _ShortPatterns.TryGetValue(f, [Long]) Then f = [Long]
            MyBase.CustomFormat = f
        End Sub

        Public Property EditingControlFormattedValue() As Object _
            Implements IDataGridViewEditingControl.EditingControlFormattedValue

            Get
                If MyBase.Checked Then _
                    Return Me.Value.ToString(MyBase.CustomFormat)
                Return _style.NullValue.ToString
            End Get
            Set(ByVal value As Object)
                Stop
            End Set
        End Property

        Private Shared _PickerInputKeys As IList(Of Keys) = New Keys() { _
            Keys.Left, Keys.Up, Keys.Down, Keys.Right, Keys.Home, Keys.End, _
            Keys.PageDown, Keys.PageUp}

        Public Function EditingControlWantsInputKey( _
            ByVal keyData As Keys, _
            ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
            Implements IDataGridViewEditingControl.EditingControlWantsInputKey

            Return _PickerInputKeys.Contains(keyData)
        End Function

        Protected Overloads Overrides Sub OnValueChanged( _
            ByVal eventargs As EventArgs)

            EditingControlValueChanged = True
            Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
            MyBase.OnValueChanged(eventargs)
        End Sub

#Region "triviale IDataGridViewEditingControl Members"

        Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
            Implements IDataGridViewEditingControl.PrepareEditingControlForEdit

            ' Kein Handlungsbedarf
        End Sub

        Private _EditingControlDataGridView As DataGridView
        Public Property EditingControlDataGridView() As DataGridView _
            Implements IDataGridViewEditingControl.EditingControlDataGridView

            Get
                Return _EditingControlDataGridView
            End Get
            Set(ByVal value As DataGridView)
                _EditingControlDataGridView = value
            End Set
        End Property

        Private _EditingControlRowIndex As Integer
        Public Property EditingControlRowIndex() As Integer _
            Implements IDataGridViewEditingControl.EditingControlRowIndex

            Get
                Return _EditingControlRowIndex
            End Get
            Set(ByVal value As Integer)
                _EditingControlRowIndex = value
            End Set
        End Property

        Private _EditingControlValueChanged As Boolean
        Public Property EditingControlValueChanged() As Boolean _
            Implements IDataGridViewEditingControl.EditingControlValueChanged

            Get
                Return _EditingControlValueChanged
            End Get
            Set(ByVal value As Boolean)
                _EditingControlValueChanged = value
            End Set
        End Property

        Public ReadOnly Property EditingPanelCursor() As Cursor _
            Implements IDataGridViewEditingControl.EditingPanelCursor

            Get
                Return MyBase.Cursor
            End Get
        End Property

        Public ReadOnly Property RepositionEditingControlOnValueChange() _
            As Boolean _
            Implements _
                IDataGridViewEditingControl.RepositionEditingControlOnValueChange

            Get
            Return False
            End Get
        End Property

        Public Function GetEditingControlFormattedValue( _
            ByVal context As DataGridViewDataErrorContexts) As Object _
            Implements _
                IDataGridViewEditingControl.GetEditingControlFormattedValue

            Return Me.EditingControlFormattedValue
        End Function
#End Region 'triviale IDataGridViewEditingControl Members

    End Class 'TimePickerColumn.EditingControl
End Class

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.