Custom Datagrid Column Styles

vinnie881

Well-known member
Joined
Sep 3, 2006
Messages
152
Programming Experience
3-5
I have spent literally 4 hours on this and can not get anywhere.

I have a windows datagrid control where I want to have a DatagridTextBox Column.

Here's the issue.

Under my Mouse up event on the datagrid I have the following code
VB.NET:
        Try
            Dim pt = New Point(e.X, e.Y)
            Dim hit As DataGrid.HitTestInfo = sender.HitTest(pt)

            If hit.Type = DataGrid.HitTestType.Cell Then
                sender.CurrentCell = New DataGridCell(hit.Row, hit.Column)
                sender.Select(hit.Row)
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

THis code basically highlights the entire row each time a user clicks is. But since it highlights the row, It will not let me type in the text box. (Basically as soon as I clickdown the mouse button on the cell I can edit it, but when I let go of of it (MOUSE UP), it fires the mouseup event and kicks me out of editing the cell.

So I built a new DataGridTextBox Component class to accomidate this, but I have a issue with this class as well( It rectifies the issue with exiting the cell on the mouse up, but I get a (Referance is not set to object Error) when I do this.

1. Click on the text box I want to edit
2. Move the scroll bar at the bottom over so Where my edited cell at step 1 was I have a new cell.
3. Then click the new cell.

I can not trap this error either becaues it's happening in the base class.

Here's my new Textbox Component class

VB.NET:
Imports System
Imports System.Drawing
Imports System.Diagnostics
Imports System.Windows.Forms

Namespace MyColumnStyles.DataGridColumnStyles 

    Public Class DataGridColoredTextBoxColumn

#Region " Declarations "

        Inherits DataGridTextBoxColumn

        Public ColumnTextBox As System.Windows.Forms.TextBox

        Private mcmSource As System.Windows.Forms.CurrencyManager
        Private mintRowNum As Integer
        Private mblnEditing As Boolean
        Private mRowType As Object

#End Region

#Region " Constructor "

        Public Sub New()

            mcmSource = Nothing
            mblnEditing = False

            ColumnTextBox = New NoKeyUpTextBox
            Me.Width = ColumnTextBox.Width
            AddHandler ColumnTextBox.Leave, AddressOf LeaveComboBox
            AddHandler TextBox.Enter, AddressOf ComboStartEditing

        End Sub

#End Region

#Region " Private Methods "
        Private Sub HandleScroll(ByVal sender As Object, ByVal e As EventArgs)
            If ColumnTextBox.Visible Then ColumnTextBox.Hide()
        End Sub
        Private Sub ComboStartEditing(ByVal sender As Object, ByVal e As EventArgs)
            mblnEditing = True
            MyBase.ColumnStartedEditing(sender)
        End Sub
        Private Sub LeaveComboBox(ByVal sender As Object, ByVal e As EventArgs)
            Try
                If mblnEditing = True Then
                    ColumnTextBoxCommit(mcmSource, mintRowNum)
                    Invalidate()
                    mblnEditing = False
                End If

                ColumnTextBox.Hide()
                AddHandler Me.DataGridTableStyle.DataGrid.Scroll, New EventHandler(AddressOf HandleScroll)

            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub
#End Region

#Region " Overridden Methods "

        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 backBrush As System.Drawing.Brush, _
ByVal foreBrush As System.Drawing.Brush, ByVal alignToRight As Boolean)
            Try
                Dim sf As New StringFormat
                sf.Alignment = StringAlignment.Near
                sf.LineAlignment = StringAlignment.Center
                Dim boundsF As New System.Drawing.RectangleF( _
                 CType(bounds.X, Single), _
                 CType(bounds.Y, Single), _
                 CType(bounds.Width, Single), _
                 CType(bounds.Height, Single))
                Dim x As String = String.Empty
                Dim dg As DataGrid = Me.DataGridTableStyle.DataGrid
                If Not Me.GetColumnValueAtRow([source], rowNum).ToString() Is DBNull.Value Then
                    x = Me.GetColumnValueAtRow([source], rowNum).ToString()
                End If
                Dim dgfont As System.Drawing.Font = Me.DataGridTableStyle.DataGrid.Font

                Dim Backcolor As SolidBrush
                Backcolor = backBrush
                If Not Backcolor.Color.Equals(SystemColors.ActiveCaption) Then
                    backBrush = New SolidBrush(System.Drawing.Color.LightSalmon)
                End If

                g.FillRectangle(backBrush, bounds)
                g.DrawString(x, dgfont, foreBrush, boundsF, sf)

            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        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)
            'mblnEditing = True
            Try
                Me.mcmSource = [source]
                Me.mintRowNum = rowNum
                MyBase.Edit([source], rowNum, bounds, [readOnly], instantText, cellIsVisible)

                mintRowNum = rowNum
                mcmSource = [source]

                With ColumnTextBox
                    .Parent = Me.TextBox.Parent
                    .Location = Me.TextBox.Location
                    .Size = New Size(Me.TextBox.Size.Width, .Size.Height)
                    Me.TextBox.Visible = False
                    .Visible = True
                    ColumnTextBox.Text = Me.GetColumnValueAtRow(source, rowNum)
                    Me.mRowType = Me.GetColumnValueAtRow(source, rowNum)
                    AddHandler Me.DataGridTableStyle.DataGrid.Scroll, AddressOf HandleScroll
                    .BringToFront()
                    .Focus()
                End With
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub

        Protected Overrides Function Commit( _
                    ByVal dataSource As System.Windows.Forms.CurrencyManager, _
                    ByVal rowNum As Integer) As Boolean
            'Nothing Happens here
        End Function
        Private Function ColumnTextBoxCommit(ByVal Datasource As System.Windows.Forms.CurrencyManager, _
                        ByVal RowNum As Integer) As Boolean
            Try
                If mblnEditing Then
                    Dim Valuetype As String = Me.GetColumnValueAtRow(Datasource, RowNum).GetType().ToString
                    Select Case Valuetype
                        Case "System.Boolean"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Boolean))
                        Case "System.Double"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Double))
                        Case "System.String"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, String))
                        Case "System.Int16"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Int16))
                        Case "System.Int32"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Int32))
                        Case "System.Int64"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Int64))
                        Case "System.Byte"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Byte))
                        Case "System.Char"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Char))
                        Case "System.DateTime"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, DateTime))
                        Case "System.Decimal"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Decimal))
                        Case "System.Double"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Double))
                        Case "System.Object"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Object))
                        Case "System.Single"
                            MyBase.SetColumnValueAtRow(Datasource, RowNum, CType(ColumnTextBox.Text, Single))
                        Case Else
                            Throw New Exception("Unknown Object Type " & Valuetype)
                    End Select
                End If
                Return True
            Catch ex As Exception
                MsgBox(ex.Message)
                Invalidate()
                ColumnTextBox.Hide()
                mblnEditing = False
            End Try
        End Function
#End Region
    End Class 'DataGridTextBoxColumn
End Namespace 'MyColumnStyles.DataGridColumnStyles

I can not figure this one out... THANKS in advance for any help.
 
I figured It out

It's amazing, how you can spend so much time on something and get no where, but take a 10 minute break and your able to come back and solve the issue in 2 minutes.


After all this time, the issue was this 1 Line
VB.NET:
AddHandler TextBox.Enter, AddressOf ComboStartEditing

it should've read

VB.NET:
AddHandler ColumnTextBox.Enter, AddressOf ComboStartEditing

It seems that because of that syntax the datagrid column was getting put into edit mode when it wasn't supposed to causing it to not properly be exited when I scrolled to he next cell and clicked.

On a side note though it's a very good class for anyone who wants complete control over their textbox columns, so feel free to use. It's a fairly good template for anyone that wants to add other types of datagrid column styles as well (Progress bar, datetime, anything..)
 
Back
Top