DatagridStyle Control problem

B

Billy Jacobs

I have created a DataGridColumnDatePicker 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 DataGridColumnDatePicker
Inherits DataGridTextBoxColumn

Private WithEvents myDatePicker As DateTimePicker
Private cm As CurrencyManager
Private iCurrentRow As Int32



Public Sub New(ByVal Container As
System.ComponentModel.IContainer)
MyClass.New()
'Required for Windows.Forms Class Composition
Designer support
Container.Add(Me)

Me.cm = Nothing

'Create datetimepicker and force DropDownList
style
Me.myDatePicker = New DateTimePicker
myDatePicker.Format = DateTimePickerFormat.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(ByVal sender As Object,
ByVal e As EventArgs) Handles myDatePicker.ValueChanged
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicker.Value.ToShortDateString, Object),
DataRowView)
'Dim s As String = CType(rowView.Row
(Me.myDatePicker.Value), String)
Try
Dim s As String =
Me.myDatePicker.Value.ToShortDateString
Debug.WriteLine(String.Format("Leave: {0}
{1}", Me.myDatePicker.Value.ToShortTimeString, s))

SetColumnValueAtRow(Me.cm, Me.iCurrentRow, s)
Invalidate()
Me.myDatePicker.Hide()
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
End Try
End Sub
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
'Add any initialization after the
InitializeComponent() 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.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Component Designer
Private components As System.ComponentModel.IContainer

'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.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub


Protected Overrides Function GetColumnValueAtRow
(ByVal source As System.Windows.Forms.CurrencyManager,
ByVal rowNum As Integer) As Object
Return MyBase.GetColumnValueAtRow(source, 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 SetColumnValueAtRow(ByVal
source As System.Windows.Forms.CurrencyManager, ByVal
rowNum As Int32, ByVal value As Object)

'Debug.WriteLine(String.Format("SetColumnValueAtRow
{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 = (CurrencyManager))
' (this.DataGridTableStyle.DataGrid.BindingContext
[this.comboBox.DataSource]);
'// Assumes the associated DataGrid is bound to a
DataView, or DataTable that
'// implements a default DataView
'DataView dataview = ((DataView)cm.List);
'int i;

'for (i = 0; i < dataview.Count; i++)
'{
' if (s.Equals(dataview
[this.comboBox.DisplayMember]))
' break;
'}

'// If set item was found return corresponding value,
otherwise return DbNull.Value
' If (i < DataView.Count) Then
' s = dataview[this.comboBox.ValueMember];
' Else
' s = DBNull.Value;

'base.SetColumnValueAtRow(source, rowNum, s);
' End Sub
Protected Overrides Sub Abort(ByVal rowNum As Integer)
MyBase.Abort(rowNum)
End Sub

Protected Overrides Function Commit(ByVal dataSource
As System.Windows.Forms.CurrencyManager, ByVal rowNum As
Integer) As Boolean
Try
MyBase.Commit(dataSource, rowNum)
Catch ex As Exception
Throw New Exception("Error in Commit: " &
ex.Message, ex.InnerException)
End Try
End Function

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)

Try
Debug.WriteLine(String.Format("Edit {0}",
rowNum))
MyBase.Edit(source, 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.DataGridTableStyle.DataGrid.Scroll, AddressOf
DataGrid_Scroll

' Site the datetimepicker control within
the bounds of the current cell
Me.myDatePicker.Parent = Me.TextBox.Parent
Dim rect As Rectangle =
Me.DataGridTableStyle.DataGrid.GetCurrentCellBounds()
Me.myDatePicker.Location = rect.Location
Me.myDatePicker.Size = New Size
(Me.TextBox.Size.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.Text, 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.Message,
ex.InnerException)
End Try
End Sub

Private Sub date_Time_Picker_Leave(ByVal sender As
Object, ByVal e As EventArgs) Handles myDatePicker.Leave
Try
'Dim rowView As DataRowView = CType(CType
(Me.myDatePicker.Value.ToShortDateString, Object),
DataRowView)
'Dim s As String = CType(rowView.Row
(Me.myDatePicker.Value), String)
Dim s As String =
Me.myDatePicker.Value.ToShortDateString
Debug.WriteLine(String.Format("Leave: {0}
{1}", Me.myDatePicker.Value.ToShortDateString, s))

SetColumnValueAtRow(Me.cm, Me.iCurrentRow, s)
Me.TextBox.Text = s
Invalidate()

Me.myDatePicker.Hide()
RemoveHandler
Me.DataGridTableStyle.DataGrid.Scroll, AddressOf
DataGrid_Scroll
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
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.Message,
ex.InnerException)
End Try
End Sub

Protected Overrides Function GetMinimumHeight() As
Integer
Try
Return MyBase.GetMinimumHeight
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
End Try
End Function

Protected Overrides Function GetPreferredHeight(ByVal
g As System.Drawing.Graphics, ByVal value As Object) As
Integer
Try
Return MyBase.GetPreferredHeight(g, value)
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
End Try
End Function

Protected Overrides Function GetPreferredSize(ByVal g
As System.Drawing.Graphics, ByVal value As Object) As
System.Drawing.Size
Try
Return MyBase.GetPreferredSize(g, value)
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
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.CurrencyManager, ByVal rowNum As
Integer)
Try
MyBase.Paint(g, bounds, source, rowNum)
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
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.CurrencyManager, ByVal rowNum As
Integer, ByVal alignToRight As Boolean)
Try
MyBase.Paint(g, bounds, source, rowNum,
alignToRight)
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
End Try
End Sub
End Class

***Form Code***
Friend WithEvents DataGridTableStyle1 As
System.Windows.Forms.DataGridTableStyle
Friend WithEvents DataGridDateTimePicker1 As
DataGridColumnDatePicker

Me.DataGridTableStyle1.GridColumnStyles.AddRange(New
System.Windows.Forms.DataGridColumnStyle() {
Me.DataGridDateTimePicker1})

Me.DataGridDateTimePicker1 = New
CSEPP_Admin_Tool.DataGridColumnDatePicker(Me.components)

Me.DataGridDateTimePicker1.Format = ""
Me.DataGridDateTimePicker1.FormatInfo = Nothing
Me.DataGridDateTimePicker1.HeaderText = "Date"
Me.DataGridDateTimePicker1.MappingName
= "EntryDate"
Me.DataGridDateTimePicker1.Width = 75
 
B

Billy Jacobs

I fixed my problem. The problem was that I was overriding
the Commit Function and I was not returning a value. I
did not even need to override that function. I just got
the overrides automatically when I inherited from the
DataGridTextBoxColumn. I had a bunch of other overrides I
didn't need.

Here is the cleaned up code for anyone who wants a
DataGridColumnDatePicker Column.

Public Class DataGridColumnDatePicker
Inherits DataGridTextBoxColumn
Private WithEvents myDatePicker As DateTimePicker
Private cm As CurrencyManager
Private iCurrentRow As Int32
'Required by the Component Designer
Private components As System.ComponentModel.IContainer

Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
'Add any initialization after the
InitializeComponent() call
'Required for Windows.Forms Class Composition
Designer support
Me.cm = Nothing
'Create datetimepicker and force Short DateTime
Format.
Me.myDatePicker = New DateTimePicker
myDatePicker.Format = DateTimePickerFormat.Short
' Add event handler for notification of when
ComboBox loses focus
'Container.Add(Me)
End Sub

' On myDatePicker Value changed, set the column
value, hide the date time picker,
' and unregister scroll event handler
Private Sub Change_Value(ByVal sender As Object,
ByVal e As EventArgs) Handles myDatePicker.ValueChanged
Try
Dim s As String =
Me.myDatePicker.Value.ToShortDateString
Debug.WriteLine(String.Format("Leave: {0}
{1}", Me.myDatePicker.Value.ToShortTimeString, s))
SetColumnValueAtRow(Me.cm, Me.iCurrentRow,
CDate(Me.myDatePicker.Value.ToShortDateString))
Me.TextBox.Text =
myDatePicker.Value.ToShortDateString
Invalidate()
Me.myDatePicker.Hide()
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
End Try
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.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'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.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
components = New System.ComponentModel.Container
components.Add(Me)
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)
Try
Debug.WriteLine(String.Format("Edit {0}",
rowNum))
MyBase.Edit(source, 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.DataGridTableStyle.DataGrid.Scroll, AddressOf
DataGrid_Scroll

' Site the datetimepicker control within
the bounds of the current cell
Me.myDatePicker.Parent = Me.TextBox.Parent
Dim rect As Rectangle =
Me.DataGridTableStyle.DataGrid.GetCurrentCellBounds()
Me.myDatePicker.Location = rect.Location
Me.myDatePicker.Size = New Size
(Me.TextBox.Size.Width, Me.myDatePicker.Size.Height)

' Set combo box selection to given text
If Me.TextBox.Text <> "(null)" Then
Me.myDatePicker.Value = CType
(Me.TextBox.Text, 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.Message,
ex.InnerException)
End Try
End Sub

Private Sub date_Time_Picker_Leave(ByVal sender As
Object, ByVal e As EventArgs) Handles myDatePicker.Leave
Try
Dim s As String =
Me.myDatePicker.Value.ToShortDateString
Debug.WriteLine(String.Format("Leave: {0}
{1}", Me.myDatePicker.Value.ToShortDateString, s))

SetColumnValueAtRow(Me.cm, Me.iCurrentRow,
CDate(Me.myDatePicker.Value.ToShortDateString))
Me.TextBox.Text = s
If myDatePicker.Visible = True Then
Me.myDatePicker.Hide()
End If
Invalidate()
RemoveHandler
Me.DataGridTableStyle.DataGrid.Scroll, AddressOf
DataGrid_Scroll
Catch ex As Exception
Throw New Exception(ex.Message,
ex.InnerException)
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.Message,
ex.InnerException)
End Try
End Sub

End Class
 
J

John Stannard

Hi Billy,

I tried to use your class, but the Edit method of the
DataGridTextBoxColumn (with that signature) can't be overridden. I
don't know how you got around this.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top