Custom DataGridColumnStyle Null error

lespaul36

Member
Joined
Dec 12, 2007
Messages
7
Programming Experience
3-5
I have been working on a custom datagridcolumnstyle that uses a combo box when in edit mode. It the box is showing, but not expanded and I click on another cell in the same row, I get a null reference exception without source code. If I click on another row I get an object not set to reference error, but it shows a dialog box. If I expand the combo box it works just fine. I am thinking it is an internal bug, but how do I work around it?

I would show code, but it is way to large. Here is the style code though.

Public Class HSDropBoxColumn
    Inherits DataGridColumnStyle
    Implements IColumnInterface
    Implements ISetCellFormat

    Friend WithEvents mListBox As New ComboBox
    Private mDataGrid As DataGrid = Nothing

    Private mblnIsEditing As Boolean = False

    Public Sub New(ByVal Values As String())
        mListBox.Items.AddRange(Values)
        mListBox.Visible = False
        mListBox.Height = 50
        mListBox.DropDownStyle = ComboBoxStyle.DropDownList
    End Sub

    Protected Overrides Sub Abort(rowNum As Integer)
        mblnIsEditing = False
            
        mDataGrid.Controls.Remove(mListBox)
        Invalidate()
    End Sub

    Protected Overrides Function Commit(dataSource As System.Windows.Forms.CurrencyManager, rowNum As Integer) As Boolean
        If Not mblnIsEditing Then
            Return True
        End If
        If mListBox Is Nothing Then Return True
        mblnIsEditing = False

        Dim objOld, objNew As Object
        Try
            objOld = GetColumnValueAtRow(dataSource, rowNum)
        Catch exr As IndexOutOfRangeException
            Return True
            Exit Function
        End Try

        Try
            objNew = mListBox.SelectedItem.ToString
        Catch ex As Exception
            Return True
        End Try


        If objOld Is DBNull.Value And objNew Is DBNull.Value Then
            Return False
        ElseIf objOld Is DBNull.Value And Not objNew Is DBNull.Value Then
            If TypeOf objNew Is String Then
                SetColumnValueAtRow(dataSource, rowNum, CStr(objNew))
                OnCellValueChanged(New CellValueChangedEventArgs(rowNum, Me.DataGridTableStyle.GridColumnStyles.IndexOf(Me), objOld, objNew))
            Else
                Return False
            End If
        ElseIf Not objOld Is DBNull.Value And objNew Is DBNull.Value Then
            SetColumnValueAtRow(dataSource, rowNum, DBNull.Value)
            OnCellValueChanged(New CellValueChangedEventArgs(rowNum, Me.DataGridTableStyle.GridColumnStyles.IndexOf(Me), objOld, objNew))
        ElseIf Not objOld Is DBNull.Value And Not objNew Is DBNull.Value Then
            If TypeOf objOld Is String And TypeOf objNew Is String Then
                If CStr(objOld) <> CStr(objNew) Then
                    SetColumnValueAtRow(dataSource, rowNum, CStr(objNew))
                    OnCellValueChanged(New CellValueChangedEventArgs(rowNum, Me.DataGridTableStyle.GridColumnStyles.IndexOf(Me), objOld, objNew))
                Else
                    Return False
                End If
            End If
        End If

        Invalidate()

        Me.mListBox.Visible = False
        Return True
    End Function

    Protected Overrides Function GetMinimumHeight() As Integer
        Return mListBox.PreferredHeight + 4
    End Function

    Protected Overrides Function GetPreferredHeight(g As System.Drawing.Graphics, value As Object) As Integer
        Return mListBox.PreferredHeight + 4
    End Function

    Protected Overrides Function GetPreferredSize(g As System.Drawing.Graphics, value As Object) As System.Drawing.Size
        Return New Size(100, mListBox.PreferredHeight + 4)
    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)
        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)
        Paint(g, bounds, [source], rowNum, Brushes.Red, _
             Brushes.Blue, alignToRight)
    End Sub

    Protected Overloads Overrides Sub Paint(ByVal g As Graphics, _
            ByVal bounds As Rectangle, ByVal [source] As CurrencyManager, _
            ByVal rowNum As Integer, ByVal backBrush As Brush, _
            ByVal foreBrush As Brush, ByVal alignToRight As Boolean)

        Dim e As HSDataGridFormatCellEventArgs = Nothing
        Dim pintCol As Integer = 0

        Try
            e = New HSDataGridFormatCellEventArgs(rowNum, pintCol, Me.GetColumnValueAtRow([source], rowNum))
            RaiseEvent SetCellFormat(Me, e)

        Catch ex As Exception

        End Try

        Dim pstrVal As String = String.Empty
        Try
            pintCol = Me.DataGridTableStyle.GridColumnStyles.IndexOf(Me)
        Catch ex As Exception

        End Try

        If TypeOf source.Current Is DataRowView Then
            Dim drv As DataRowView = DirectCast(source.Current, DataRowView)
            Dim r As DataRow = drv.DataView.Table.Rows(rowNum)

        End If
        g.FillRectangle(backBrush, bounds)
        'RaiseEvent SetCellFormat(Me, e)

        ' assume we will call the baseclass
        Dim callBaseClass As Boolean = True

        Dim pbrshBackBrush As SolidBrush
        Dim pbrshForeBrush As SolidBrush

        ' check the brushes returned from the event
        If Not (e.BackBrush Is Nothing) Then
            pbrshBackBrush = e.BackBrush
        Else
            pbrshBackBrush = New SolidBrush(Color.White)
        End If

        If Not (e.ForeBrush Is Nothing) Then
            pbrshForeBrush = e.ForeBrush
        Else
            pbrshForeBrush = New SolidBrush(Color.Black)
        End If

        Me.DataGridTableStyle.HeaderBackColor = e.HeaderBackColor
        Me.DataGridTableStyle.HeaderForeColor = e.HeaderForeColor
        Me.DataGridTableStyle.GridLineColor = e.GridLineColor

        ' check the UseBaseClassDrawing property
        If Not e.UseBaseClassDrawing Then
            callBaseClass = False
        End If

        If e.CurrentCellValue Is DBNull.Value Then
            pstrVal = "[null]"
        Else
            pstrVal = CStr(e.CurrentCellValue)
        End If


        Try
            g.FillRectangle(pbrshBackBrush, bounds)
            Dim pt As New PointF
            Dim f As Font = Me.DataGridTableStyle.DataGrid.Font
            Dim siz As SizeF = g.MeasureString(pstrVal, f)
            Dim psngTop As Single = (bounds.Height \ 2) - (siz.Height \ 2)
            psngTop = bounds.Top + psngTop
            Dim r As New RectangleF(bounds.X, psngTop, bounds.Width, siz.Height)
            Dim sf As New StringFormat
            If alignToRight Then
                sf.LineAlignment = StringAlignment.Far
            Else
                sf.LineAlignment = StringAlignment.Near
            End If
            g.DrawString(pstrVal, f, pbrshForeBrush, r, sf)

            sf.Dispose()
        Catch ex As Exception

        End Try

    End Sub

    Protected Overrides Sub SetDataGridInColumn(ByVal value As DataGrid)
        MyBase.SetDataGridInColumn(value)

        If Not value Is Nothing Then
            mDataGrid = value
        End If
    End Sub

    Protected Overridable Sub OnCellValueChanged(ByVal e As CellValueChangedEventArgs)
        RaiseEvent CellValueChanged(Me, e)
    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)
        Dim objVal As Object = GetColumnValueAtRow([source], rowNum)
        Dim value As String = String.Empty

        If Not TypeOf objVal Is DBNull Then
            value = CStr(objVal)
        End If

        If mListBox Is Nothing Then Exit Sub

        mDataGrid.Controls.Add(mListBox)
        If cellIsVisible Then
            mListBox.Width = bounds.Width
            mListBox.Location = bounds.Location
            mListBox.Height = 50
            mListBox.SelectedItem = value
            mListBox.Visible = True
        Else
            mListBox.SelectedItem = value
            mListBox.Visible = False
        End If

        If mListBox.Visible Then
            DataGridTableStyle.DataGrid.Invalidate(bounds)
        End If

        Me.mblnIsEditing = True

        mListBox.Focus()
    End Sub

    Public Event CellValueChanged(sender As Object, e As CellValueChangedEventArgs) Implements IColumnInterface.CellValueChanged

    Public Event SetCellFormat(sender As Object, e As HSDataGridFormatCellEventArgs) Implements ISetCellFormat.SetCellFormat
End Class
 
Last edited by a moderator:
Back
Top