I have created a DataGridColumnD atePicker Component so
that I can put a datetimepicker control in my datagrid.
It almost works.
When I put my mouse in the cell it changes to a
datetimepicker control. I can then select a date which
displays in the cell. When I leave the cell however I get
the following error:
Error Caption: Error when committing the row to the
original data store.
Error Message: Object reference not set to an instance of
an object. Do you want to correct the value.
Here is my class. (At the ver bottom are the declarations
for the grid control in my form)
Public Class DataGridColumnD atePicker
Inherits DataGridTextBox Column
Private WithEvents myDatePicker As DateTimePicker
Private cm As CurrencyManager
Private iCurrentRow As Int32
Public Sub New(ByVal Container As
System.Componen tModel.IContain er)
MyClass.New()
'Required for Windows.Forms Class Composition
Designer support
Container.Add(M e)
Me.cm = Nothing
'Create datetimepicker and force DropDownList
style
Me.myDatePicker = New DateTimePicker
myDatePicker.Fo rmat = DateTimePickerF ormat.Short
' Add event handler for notification of when
ComboBox loses focus
End Sub
' On myDatePicker Value changed, set the column
value, hide the date time picker,
' and unregister scroll event handler
Private Sub Change_Value(By Val sender As Object,
ByVal e As EventArgs) Handles myDatePicker.Va lueChanged
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicke r.Value.ToShort DateString, Object),
DataRowView)
'Dim s As String = CType(rowView.R ow
(Me.myDatePicke r.Value), String)
Try
Dim s As String =
Me.myDatePicker .Value.ToShortD ateString
Debug.WriteLine (String.Format( "Leave: {0}
{1}", Me.myDatePicker .Value.ToShortT imeString, s))
SetColumnValueA tRow(Me.cm, Me.iCurrentRow, s)
Invalidate()
Me.myDatePicker .Hide()
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeCompo nent()
'Add any initialization after the
InitializeCompo nent() call
End Sub
'Component overrides dispose to clean up the
component list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Disp ose()
End If
End If
MyBase.Dispose( disposing)
End Sub
'Required by the Component Designer
Private components As System.Componen tModel.IContain er
'NOTE: The following procedure is required by the
Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnos tics.DebuggerSt epThrough()> Private
Sub InitializeCompo nent()
components = New System.Componen tModel.Containe r
End Sub
Protected Overrides Function GetColumnValueA tRow
(ByVal source As System.Windows. Forms.CurrencyM anager,
ByVal rowNum As Integer) As Object
Return MyBase.GetColum nValueAtRow(sou rce, rowNum)
End Function
' Given a row and a display member, iterating over
bound datasource to find
' the associated value member. Set this value member.
' Protected Overloads Sub SetColumnValueA tRow(ByVal
source As System.Windows. Forms.CurrencyM anager, ByVal
rowNum As Int32, ByVal value As Object)
'Debug.WriteLin e(String.Format ("SetColumnValu eAtRow
{0} {1}", rowNum, value));
'object s = value;
'// Iterate through the datasource bound to the
ColumnComboBox
'// Don't confuse this datasource with the datasource
of the associated datagrid
' CurrencyManager (cm = (CurrencyManage r))
' (this.DataGridT ableStyle.DataG rid.BindingCont ext
[this.comboBox.D ataSource]);
'// Assumes the associated DataGrid is bound to a
DataView, or DataTable that
'// implements a default DataView
'DataView dataview = ((DataView)cm.L ist);
'int i;
'for (i = 0; i < dataview.Count; i++)
'{
' if (s.Equals(datav iew[i]
[this.comboBox.D isplayMember]))
' break;
'}
'// If set item was found return corresponding value,
otherwise return DbNull.Value
' If (i < DataView.Count) Then
' s = dataview[i][this.comboBox.V alueMember];
' Else
' s = DBNull.Value;
'base.SetColumn ValueAtRow(sour ce, rowNum, s);
' End Sub
Protected Overrides Sub Abort(ByVal rowNum As Integer)
MyBase.Abort(ro wNum)
End Sub
Protected Overrides Function Commit(ByVal dataSource
As System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer) As Boolean
Try
MyBase.Commit(d ataSource, rowNum)
Catch ex As Exception
Throw New Exception("Erro r in Commit: " &
ex.Message, ex.InnerExcepti on)
End Try
End Function
Protected Overloads Overrides Sub Edit(ByVal source
As System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer, ByVal bounds As System.Drawing. Rectangle, ByVal
[readOnly] As Boolean, ByVal instantText As String, ByVal
cellIsVisible As Boolean)
Try
Debug.WriteLine (String.Format( "Edit {0}",
rowNum))
MyBase.Edit(sou rce, rowNum, bounds,
[readOnly], instantText, cellIsVisible)
If Not [readOnly] AndAlso cellIsVisible Then
' Save current row in the datagrid and
currency manager associated with
' the data source for the datagrid
Me.iCurrentRow = rowNum
Me.cm = source
'Add event handler for datagrid scroll
notification
AddHandler
Me.DataGridTabl eStyle.DataGrid .Scroll, AddressOf
DataGrid_Scroll
' Site the datetimepicker control within
the bounds of the current cell
Me.myDatePicker .Parent = Me.TextBox.Pare nt
Dim rect As Rectangle =
Me.DataGridTabl eStyle.DataGrid .GetCurrentCell Bounds()
Me.myDatePicker .Location = rect.Location
Me.myDatePicker .Size = New Size
(Me.TextBox.Siz e.Width, Me.myDatePicker .Size.Height)
' Set combo box selection to given text
'If Me.TextBox.Text <> vbNull Then
If Me.TextBox.Text <> "(null)" Then
Me.myDatePicker .Value = CType
(Me.TextBox.Tex t, Date)
Else
Me.myDatePicker .Value = Now.Date
End If
' Make the datetime picker visible and
place on top text box control
Me.myDatePicker .Show()
Me.myDatePicker .BringToFront()
Me.myDatePicker .Focus()
End If
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Private Sub date_Time_Picke r_Leave(ByVal sender As
Object, ByVal e As EventArgs) Handles myDatePicker.Le ave
Try
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicke r.Value.ToShort DateString, Object),
DataRowView)
'Dim s As String = CType(rowView.R ow
(Me.myDatePicke r.Value), String)
Dim s As String =
Me.myDatePicker .Value.ToShortD ateString
Debug.WriteLine (String.Format( "Leave: {0}
{1}", Me.myDatePicker .Value.ToShortD ateString, s))
SetColumnValueA tRow(Me.cm, Me.iCurrentRow, s)
Me.TextBox.Text = s
Invalidate()
Me.myDatePicker .Hide()
RemoveHandler
Me.DataGridTabl eStyle.DataGrid .Scroll, AddressOf
DataGrid_Scroll
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Private Sub DataGrid_Scroll (ByVal sender As Object,
ByVal e As EventArgs)
Try
Debug.WriteLine ("Scroll")
Me.myDatePicker .Hide()
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Protected Overrides Function GetMinimumHeigh t() As
Integer
Try
Return MyBase.GetMinim umHeight
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overrides Function GetPreferredHei ght(ByVal
g As System.Drawing. Graphics, ByVal value As Object) As
Integer
Try
Return MyBase.GetPrefe rredHeight(g, value)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overrides Function GetPreferredSiz e(ByVal g
As System.Drawing. Graphics, ByVal value As Object) As
System.Drawing. Size
Try
Return MyBase.GetPrefe rredSize(g, value)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overloads Overrides Sub Paint(ByVal g As
System.Drawing. Graphics, ByVal bounds As
System.Drawing. Rectangle, ByVal source As
System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer)
Try
MyBase.Paint(g, bounds, source, rowNum)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
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.CurrencyM anager, ByVal rowNum As
Integer, ByVal alignToRight As Boolean)
Try
MyBase.Paint(g, bounds, source, rowNum,
alignToRight)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
End Class
***Form Code***
Friend WithEvents DataGridTableSt yle1 As
System.Windows. Forms.DataGridT ableStyle
Friend WithEvents DataGridDateTim ePicker1 As
DataGridColumnD atePicker
Me.DataGridTabl eStyle1.GridCol umnStyles.AddRa nge(New
System.Windows. Forms.DataGridC olumnStyle() {
Me.DataGridDate TimePicker1})
Me.DataGridDate TimePicker1 = New
CSEPP_Admin_Too l.DataGridColum nDatePicker(Me. components)
Me.DataGridDate TimePicker1.For mat = ""
Me.DataGridDate TimePicker1.For matInfo = Nothing
Me.DataGridDate TimePicker1.Hea derText = "Date"
Me.DataGridDate TimePicker1.Map pingName
= "EntryDate"
Me.DataGridDate TimePicker1.Wid th = 75
that I can put a datetimepicker control in my datagrid.
It almost works.
When I put my mouse in the cell it changes to a
datetimepicker control. I can then select a date which
displays in the cell. When I leave the cell however I get
the following error:
Error Caption: Error when committing the row to the
original data store.
Error Message: Object reference not set to an instance of
an object. Do you want to correct the value.
Here is my class. (At the ver bottom are the declarations
for the grid control in my form)
Public Class DataGridColumnD atePicker
Inherits DataGridTextBox Column
Private WithEvents myDatePicker As DateTimePicker
Private cm As CurrencyManager
Private iCurrentRow As Int32
Public Sub New(ByVal Container As
System.Componen tModel.IContain er)
MyClass.New()
'Required for Windows.Forms Class Composition
Designer support
Container.Add(M e)
Me.cm = Nothing
'Create datetimepicker and force DropDownList
style
Me.myDatePicker = New DateTimePicker
myDatePicker.Fo rmat = DateTimePickerF ormat.Short
' Add event handler for notification of when
ComboBox loses focus
End Sub
' On myDatePicker Value changed, set the column
value, hide the date time picker,
' and unregister scroll event handler
Private Sub Change_Value(By Val sender As Object,
ByVal e As EventArgs) Handles myDatePicker.Va lueChanged
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicke r.Value.ToShort DateString, Object),
DataRowView)
'Dim s As String = CType(rowView.R ow
(Me.myDatePicke r.Value), String)
Try
Dim s As String =
Me.myDatePicker .Value.ToShortD ateString
Debug.WriteLine (String.Format( "Leave: {0}
{1}", Me.myDatePicker .Value.ToShortT imeString, s))
SetColumnValueA tRow(Me.cm, Me.iCurrentRow, s)
Invalidate()
Me.myDatePicker .Hide()
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeCompo nent()
'Add any initialization after the
InitializeCompo nent() call
End Sub
'Component overrides dispose to clean up the
component list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Disp ose()
End If
End If
MyBase.Dispose( disposing)
End Sub
'Required by the Component Designer
Private components As System.Componen tModel.IContain er
'NOTE: The following procedure is required by the
Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnos tics.DebuggerSt epThrough()> Private
Sub InitializeCompo nent()
components = New System.Componen tModel.Containe r
End Sub
Protected Overrides Function GetColumnValueA tRow
(ByVal source As System.Windows. Forms.CurrencyM anager,
ByVal rowNum As Integer) As Object
Return MyBase.GetColum nValueAtRow(sou rce, rowNum)
End Function
' Given a row and a display member, iterating over
bound datasource to find
' the associated value member. Set this value member.
' Protected Overloads Sub SetColumnValueA tRow(ByVal
source As System.Windows. Forms.CurrencyM anager, ByVal
rowNum As Int32, ByVal value As Object)
'Debug.WriteLin e(String.Format ("SetColumnValu eAtRow
{0} {1}", rowNum, value));
'object s = value;
'// Iterate through the datasource bound to the
ColumnComboBox
'// Don't confuse this datasource with the datasource
of the associated datagrid
' CurrencyManager (cm = (CurrencyManage r))
' (this.DataGridT ableStyle.DataG rid.BindingCont ext
[this.comboBox.D ataSource]);
'// Assumes the associated DataGrid is bound to a
DataView, or DataTable that
'// implements a default DataView
'DataView dataview = ((DataView)cm.L ist);
'int i;
'for (i = 0; i < dataview.Count; i++)
'{
' if (s.Equals(datav iew[i]
[this.comboBox.D isplayMember]))
' break;
'}
'// If set item was found return corresponding value,
otherwise return DbNull.Value
' If (i < DataView.Count) Then
' s = dataview[i][this.comboBox.V alueMember];
' Else
' s = DBNull.Value;
'base.SetColumn ValueAtRow(sour ce, rowNum, s);
' End Sub
Protected Overrides Sub Abort(ByVal rowNum As Integer)
MyBase.Abort(ro wNum)
End Sub
Protected Overrides Function Commit(ByVal dataSource
As System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer) As Boolean
Try
MyBase.Commit(d ataSource, rowNum)
Catch ex As Exception
Throw New Exception("Erro r in Commit: " &
ex.Message, ex.InnerExcepti on)
End Try
End Function
Protected Overloads Overrides Sub Edit(ByVal source
As System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer, ByVal bounds As System.Drawing. Rectangle, ByVal
[readOnly] As Boolean, ByVal instantText As String, ByVal
cellIsVisible As Boolean)
Try
Debug.WriteLine (String.Format( "Edit {0}",
rowNum))
MyBase.Edit(sou rce, rowNum, bounds,
[readOnly], instantText, cellIsVisible)
If Not [readOnly] AndAlso cellIsVisible Then
' Save current row in the datagrid and
currency manager associated with
' the data source for the datagrid
Me.iCurrentRow = rowNum
Me.cm = source
'Add event handler for datagrid scroll
notification
AddHandler
Me.DataGridTabl eStyle.DataGrid .Scroll, AddressOf
DataGrid_Scroll
' Site the datetimepicker control within
the bounds of the current cell
Me.myDatePicker .Parent = Me.TextBox.Pare nt
Dim rect As Rectangle =
Me.DataGridTabl eStyle.DataGrid .GetCurrentCell Bounds()
Me.myDatePicker .Location = rect.Location
Me.myDatePicker .Size = New Size
(Me.TextBox.Siz e.Width, Me.myDatePicker .Size.Height)
' Set combo box selection to given text
'If Me.TextBox.Text <> vbNull Then
If Me.TextBox.Text <> "(null)" Then
Me.myDatePicker .Value = CType
(Me.TextBox.Tex t, Date)
Else
Me.myDatePicker .Value = Now.Date
End If
' Make the datetime picker visible and
place on top text box control
Me.myDatePicker .Show()
Me.myDatePicker .BringToFront()
Me.myDatePicker .Focus()
End If
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Private Sub date_Time_Picke r_Leave(ByVal sender As
Object, ByVal e As EventArgs) Handles myDatePicker.Le ave
Try
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicke r.Value.ToShort DateString, Object),
DataRowView)
'Dim s As String = CType(rowView.R ow
(Me.myDatePicke r.Value), String)
Dim s As String =
Me.myDatePicker .Value.ToShortD ateString
Debug.WriteLine (String.Format( "Leave: {0}
{1}", Me.myDatePicker .Value.ToShortD ateString, s))
SetColumnValueA tRow(Me.cm, Me.iCurrentRow, s)
Me.TextBox.Text = s
Invalidate()
Me.myDatePicker .Hide()
RemoveHandler
Me.DataGridTabl eStyle.DataGrid .Scroll, AddressOf
DataGrid_Scroll
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Private Sub DataGrid_Scroll (ByVal sender As Object,
ByVal e As EventArgs)
Try
Debug.WriteLine ("Scroll")
Me.myDatePicker .Hide()
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
Protected Overrides Function GetMinimumHeigh t() As
Integer
Try
Return MyBase.GetMinim umHeight
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overrides Function GetPreferredHei ght(ByVal
g As System.Drawing. Graphics, ByVal value As Object) As
Integer
Try
Return MyBase.GetPrefe rredHeight(g, value)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overrides Function GetPreferredSiz e(ByVal g
As System.Drawing. Graphics, ByVal value As Object) As
System.Drawing. Size
Try
Return MyBase.GetPrefe rredSize(g, value)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Function
Protected Overloads Overrides Sub Paint(ByVal g As
System.Drawing. Graphics, ByVal bounds As
System.Drawing. Rectangle, ByVal source As
System.Windows. Forms.CurrencyM anager, ByVal rowNum As
Integer)
Try
MyBase.Paint(g, bounds, source, rowNum)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
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.CurrencyM anager, ByVal rowNum As
Integer, ByVal alignToRight As Boolean)
Try
MyBase.Paint(g, bounds, source, rowNum,
alignToRight)
Catch ex As Exception
Throw New Exception(ex.Me ssage,
ex.InnerExcepti on)
End Try
End Sub
End Class
***Form Code***
Friend WithEvents DataGridTableSt yle1 As
System.Windows. Forms.DataGridT ableStyle
Friend WithEvents DataGridDateTim ePicker1 As
DataGridColumnD atePicker
Me.DataGridTabl eStyle1.GridCol umnStyles.AddRa nge(New
System.Windows. Forms.DataGridC olumnStyle() {
Me.DataGridDate TimePicker1})
Me.DataGridDate TimePicker1 = New
CSEPP_Admin_Too l.DataGridColum nDatePicker(Me. components)
Me.DataGridDate TimePicker1.For mat = ""
Me.DataGridDate TimePicker1.For matInfo = Nothing
Me.DataGridDate TimePicker1.Hea derText = "Date"
Me.DataGridDate TimePicker1.Map pingName
= "EntryDate"
Me.DataGridDate TimePicker1.Wid th = 75
Comment