• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 858
  • Last Modified:

Capturing a click event for a checkbox in a datagrid

I have a datagrid with 2 checkboxes in them, I want only one of them to be checked at a time.  So basically if the user clicks one of the check boxes in the row and then clicks the other one it will uncheck the first one.

I can't use one check box because i also need a third state, and i think it makes it much more user friendly if they are seperate.  

I basically don't know how to check the event handler for a checkbox in a datagrid and then use that to set the state of the second checkbox.
0
ethnarch
Asked:
ethnarch
  • 2
  • 2
1 Solution
 
ethnarchAuthor Commented:
I found this code but it doesn't seem to be working correctly
It seems to only sometimes changed the checkboxes in the datagrid i must be doing something wrong here

    Private Sub dg_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGrid1.MouseDown
        ' X & Y are in the grid' coordinates. If they are in screen coordinates, call dataGrid1.PointToClient method
        Dim pt = New Point(e.X, e.Y)
        Dim hti As DataGrid.HitTestInfo = DataGrid1.HitTest(pt)

        If hti.Type = DataGrid.HitTestType.Cell Then
            If hti.Column = 7 Then
                Cids1.Tables(0).Rows(hti.Row).Item("UseLocationB") = False
                DataGrid1.Update()

            ElseIf hti.Column = 9 Then
                Cids1.Tables(0).Rows(hti.Row).Item("UseLocationA") = False
                DataGrid1.Update()
            End If


        End If
0
 
NetworkArchitekCommented:
Well first, why not use  radio buttons?
0
 
amyhxuCommented:
You may want to set the checkbox react to the first click. The following comment and code are copied from http://www.syncfusion.com/FAQ/WinForms/FAQ_c44c.asp#q945q

When you first click into a checkbox column, the checked state of the cell does not change. One way you can make the checked state change on the first click is to handle the grid's MouseUp event, and change the check value there.
 
     Private myCheckBoxCol As Integer = 9 'my checkbox column
 
     Private Sub DataGrid2_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles DataGrid2.MouseUp
 
          Dim hti As DataGrid.HitTestInfo = Me.dataGrid2.HitTest(e.X, e.Y)  
          Try  
               If hti.Type = DataGrid.HitTestType.Cell AndAlso hti.Column = myCheckBoxCol Then
                    Me.dataGrid2(hti.Row, hti.Column) = Not CBool(Me.dataGrid2(hti.Row, hti.Column))  
               End If  
          Catch ex As Exception  
               MessageBox.Show(ex.ToString())
          End Try
 
     End Sub 'dataGrid2_MouseUp
 
---------------------------------------------------------------------------------------------------------------------

And here is the code to catch the boolean value changes, copied from http://www.syncfusion.com/FAQ/WinForms/FAQ_c44c.asp#q874q

There is no event fired when the boolean value changes. In the attached sample, a BoolValueChanged event has been added to a columnstyle derived from DataGridBoolColumn. Catching the changes requires some effort. The strategy is to save the current value when the cell begins being edited. This is done in an override of Edit. Then in a Paint override, checks are done to see if there is a click in the checkbox cell or if the space bar is hit. If either of these situations happen when the cell is actively being edited, the bool value is changed and the event fired.

///////////////////////////////////////////////////////////////////////////////////////////

Option Strict Off
Option Explicit On

Imports Microsoft.VisualBasic
Imports System

Namespace DataGridCheckBoxChangeEvent
    Public Class BoolValueChangedEventArgs
        Inherits EventArgs
        Private _column As Integer
        Private _row As Integer
        Private _value As Boolean
        'Fields
        'Constructors
        'Methods
        Public Sub New(ByVal row As Integer, ByVal col As Integer, ByVal val As Boolean)
            MyBase.New()
            _row = row
            _column = col
            _value = val

        End Sub
        Public Property Column() As Integer
            Get

                Return _column

            End Get
            Set(ByVal Value As Integer)

                _column = Value

            End Set
        End Property
        Public Property Row() As Integer
            Get

                Return _row

            End Get
            Set(ByVal Value As Integer)

                _row = Value

            End Set
        End Property
        Public Property BoolValue() As Boolean
            Get

                Return _value

            End Get
            Set(ByVal Value As Boolean)

                _value = Value

            End Set
        End Property
    End Class
End Namespace


/////////////////////////////////////////////////////////////////////////////////////////////

Option Strict Off
Option Explicit On

Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Windows.Forms

Namespace DataGridCheckBoxChangeEvent


   
    Public Class Form1
        Inherits Form
        Private WithEvents dataGrid1 As DataGrid
        Private WithEvents myDataSet As DataSet
        Private components As Container
        'Fields
        'Constructors
        'Events
        'Methods
        Public Sub New()
            MyBase.New()
            '
            ' Required for Windows Form Designer support
            '
            InitializeComponent()
            SetUp()
            '
            ' TODO: Add any constructor code after InitializeComponent call
            '

        End Sub
        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
        Private Sub InitializeComponent()
            Me.dataGrid1 = New System.Windows.Forms.DataGrid
            CType(Me.dataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.SuspendLayout()
            '
            'dataGrid1
            '
            Me.dataGrid1.DataMember = ""
            Me.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
            Me.dataGrid1.Location = New System.Drawing.Point(48, 37)
            Me.dataGrid1.Name = "dataGrid1"
            Me.dataGrid1.Size = New System.Drawing.Size(586, 268)
            Me.dataGrid1.TabIndex = 0
            '
            'Form1
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(6, 15)
            Me.ClientSize = New System.Drawing.Size(681, 347)
            Me.Controls.Add(Me.dataGrid1)
            Me.Name = "Form1"
            Me.Text = "Form1"
            CType(Me.dataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
            Me.ResumeLayout(False)

        End Sub
        <STAThread()> _
        Public Shared Sub Main()

            Application.Run(New Form1())

        End Sub
        Private Sub SetUp()

            ' Create a DataSet with two tables and one relation.
            MakeDataSet()
            ' Bind the DataGrid to the DataSet. The dataMember
            'specifies that the Customers table should be displayed.
            dataGrid1.SetDataBinding(myDataSet, "EastCoastSales")
            'create and add a custom table style so we can
            'easily get at the behavior of a cell...
            AddCustomDataTableStyle()

        End Sub
        Private Sub AddCustomDataTableStyle()

            'STEP 1: Create a DataTable style object and set properties if required.
            Dim ts1 As DataGridTableStyle
            ts1 = New DataGridTableStyle()
            'specify the table from dataset (required step)
            ts1.MappingName = "EastCoastSales"
            ' Set other properties (optional step)
            ts1.AlternatingBackColor = Color.LightBlue
            Dim colCount As Integer
            colCount = 0
            'STEP 2: Create a string column and add it to the tablestyle
            Dim TextCol As DataGridColumnStyle
            TextCol = New DataGridTextBoxColumn()
            TextCol.MappingName = "custName"
            'from dataset table
            TextCol.HeaderText = "Customer Name"
            TextCol.Width = 100
            ts1.GridColumnStyles.Add(TextCol)
            colCount = (colCount + 1)

            'STEP 3: Create an int column style and add it to the tablestyle
            'this requires setting the format for the column through its property descriptor
            Dim pdc As PropertyDescriptorCollection
            pdc = Me.BindingContext(myDataSet, "EastCoastSales").GetItemProperties
            'now created a formated column using the pdc
            Dim csIDInt As DataGridTextBoxColumn
            csIDInt = New DataGridTextBoxColumn(pdc("CustID"), "i", True)
            csIDInt.Format = "d3"
            csIDInt.MappingName = "CustID"
            csIDInt.HeaderText = "CustID"
            csIDInt.Width = 50
            ts1.GridColumnStyles.Add(csIDInt)
            colCount = (colCount + 1)

            'STEP 4: Add the checkbox
            Dim boolCol As MyDataGridBoolColumn
            boolCol = New MyDataGridBoolColumn(colCount)
            boolCol.MappingName = "Current"
            boolCol.HeaderText = "Info Current"
            'uncomment this line to get a two-state checkbox
            CType(boolCol, DataGridBoolColumn).AllowNull = False
            boolCol.Width = 70
            'hook the new event to our handler in the grid
            AddHandler boolCol.BoolValueChanged, New MyDataGridBoolColumn.BoolValueChangedEventHandler(AddressOf HandleBoolChanges)
            ts1.GridColumnStyles.Add(boolCol)
            colCount = (colCount + 1)

            'STEP 5: Add a second checkbox
            boolCol = New MyDataGridBoolColumn(colCount)
            boolCol.MappingName = "Current2"
            boolCol.HeaderText = "Info Current2"
            CType(boolCol, DataGridBoolColumn).AllowNull = False
            boolCol.Width = 70
            'hook the new event to our handler in the grid
            AddHandler boolCol.BoolValueChanged, New MyDataGridBoolColumn.BoolValueChangedEventHandler(AddressOf HandleBoolChanges)
            ts1.GridColumnStyles.Add(boolCol)
            colCount = (colCount + 1)

            'STEP 6: Add the tablestyle to your datagrids tablestlye collection
            dataGrid1.TableStyles.Add(ts1)

        End Sub
        Private Sub MakeDataSet()

            ' Create a DataSet.
            myDataSet = New DataSet("myDataSet")
            ' Create two DataTables.
            Dim tCust As DataTable
            tCust = New DataTable("EastCoastSales")
            ' Create two columns, and add them to the first table.
            Dim cCustID As DataColumn
            cCustID = New DataColumn("CustID", GetType(System.Int32))
            Dim cCustName As DataColumn
            cCustName = New DataColumn("CustName")
            Dim cCurrent As DataColumn
            cCurrent = New DataColumn("Current", GetType(System.Boolean))
            Dim cCurrent2 As DataColumn
            cCurrent2 = New DataColumn("Current2", GetType(System.Boolean))
            tCust.Columns.Add(cCustID)
            tCust.Columns.Add(cCustName)
            tCust.Columns.Add(cCurrent)
            tCust.Columns.Add(cCurrent2)
            ' Add the tables to the DataSet.
            myDataSet.Tables.Add(tCust)
            ' Populates the tables. For each customer and order,
            'creates two DataRow variables.
            Dim newRow1 As DataRow
            ' Create three customers in the Customers Table.
            Dim i As Integer
            i = 1

            Do While (i < 4)
                newRow1 = tCust.NewRow
                newRow1("custID") = i
                ' Add the row to the Customers table.
                tCust.Rows.Add(newRow1)
                i = (i + 1)

            Loop
            ' Give each customer a distinct name.
            tCust.Rows(0)("custName") = "Alpha"
            tCust.Rows(1)("custName") = "Beta"
            tCust.Rows(2)("custName") = "Omega"
            ' Give the Current column a value.
            tCust.Rows(0)("Current") = True
            tCust.Rows(1)("Current") = True
            tCust.Rows(2)("Current") = False
            tCust.Rows(0)("Current2") = False
            tCust.Rows(1)("Current2") = True
            tCust.Rows(2)("Current2") = False

        End Sub
        Private Sub HandleBoolChanges(ByVal sender As Object, ByVal e As BoolValueChangedEventArgs)

            Dim s As String
            s = System.String.Format("Bool Changes: row {0}, col {1}   value {2}", e.Row, e.Column, e.BoolValue)
            Console.WriteLine(s)

        End Sub

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        End Sub
    End Class
End Namespace
0
 
ethnarchAuthor Commented:
thanks amy, I didn't need to actually capture the click event i guess which is a good thing, because that second half seemed a little to complicated for what i wanted.  

This code seems to have solved all my problems

     Private myCheckBoxCol As Integer = 9 'my checkbox column
 
     Private Sub DataGrid2_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles DataGrid2.MouseUp
 
          Dim hti As DataGrid.HitTestInfo = Me.dataGrid2.HitTest(e.X, e.Y)  
          Try  
               If hti.Type = DataGrid.HitTestType.Cell AndAlso hti.Column = myCheckBoxCol Then
                    Me.dataGrid2(hti.Row, hti.Column) = Not CBool(Me.dataGrid2(hti.Row, hti.Column))  
               End If  
          Catch ex As Exception  
               MessageBox.Show(ex.ToString())
          End Try
 
     End Sub 'dataGrid2_MouseUp
0
 
amyhxuCommented:
That's good. You can still save the second part for future use :-)
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now