VB.NET-Tipp 0111: DateTimePicker im DataGridView hosten
von Spatzenkanonier
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: | 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: |
' 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.