Solved

Which Events to use?

Posted on 2015-01-14
4
85 Views
Last Modified: 2015-02-02
I have a DataGridView (dgv) on a Windows form. This dgv consists of several rows with 5 columns. The problem I'm having is not knowing which Events to fire.

The scenario is that if the cursor is in the 2nd column and the cell is empty and the User presses the Down/Up Arrow Keys, the program needs to display a message that the cell cannot be empty. I'm not sure what kind of logic to use to correctly handle this situation. Each cell only takes numeric data.

Thanks!
0
Comment
Question by:BlakeMcKenna
  • 2
4 Comments
 
LVL 32

Expert Comment

by:it_saige
Comment Utility
Use the CellValidating event.  Example code from MSDN:
Private Sub dataGridView1_CellValidating(ByVal sender As Object, _
    ByVal e _
    As DataGridViewCellValidatingEventArgs) _
    Handles dataGridView1.CellValidating

    Me.dataGridView1.Rows(e.RowIndex).ErrorText = "" 
    Dim newInteger As Integer 

    ' Don't try to validate the 'new row' until finished  
    ' editing since there 
    ' is not any point in validating its initial value. 
    If dataGridView1.Rows(e.RowIndex).IsNewRow Then Return 
    If Not Integer.TryParse(e.FormattedValue.ToString(), newInteger) _
        OrElse newInteger < 0 Then

        e.Cancel = True 
        Me.dataGridView1.Rows(e.RowIndex).ErrorText = "the value must be a non-negative integer" 

    End If 
End Sub

Open in new window

-saige-
0
 
LVL 62

Expert Comment

by:Fernando Soto
Comment Utility
You could use the DataGridView.CellContentClick Event to determine which cell in which row was clicked and use the DataGridView.CellLeave Event to make sure the cell is not empty before leaving.
0
 

Author Comment

by:BlakeMcKenna
Comment Utility
Saige,

So far I think the CellValidating will work, however, I still need some tweeks. Here is what my CellValidating Event looks like:

    Private Sub dgvTension_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles dgvTension.CellValidating
        Try
            Dim cl As DataGridViewCell = dgvTension.CurrentCell

            EH.ErrorMessage = String.Empty

            Select Case e.RowIndex
                Case 0
                    Select Case e.ColumnIndex
                        Case 2  'Output Cell (0 Load)
                            If cl.Value = String.Empty Then
                                gblnEmptyCell = True
                            End If
                    End Select
                Case Else
                    Select Case e.ColumnIndex
                        Case 1  'Output Cell 
                            If cl.Value = String.Empty Then
                                gblnEmptyCell = True
                            End If
                        Case 2

                    End Select
            End Select

            If gblnEmptyCell Then
                e.Cancel = True
                gblnEmptyCell = False
                EH.ErrorMessage = "Cell cannot be empty!" & "~I"
                'dgvTension.CurrentCell = dgvTension(iTensionColIDX, iTensionRowIDX)
            End If

        Catch ex As Exception
            EH.ErrorMessage = "frmCalibration_3/dgvTension_CellValidating() - " & ex.Message & "...Contact Engineering!" & "~E"
        End Try

        EH.ProcessMessages(Me, sbr, EH.ErrorMessage)
    End Sub

Open in new window


But here is my problem, when this event fires, the cl.Value has a string value of "" even though there is a numeric value in the cell so consequently it will execute the last If statement in the Event. I thought when the CellValidating Event fires...if there is data in a specific cell, it will show (I'm just declaring a variable as DataGridViewCell and assigning the CurrentCell to it).
0
 
LVL 32

Accepted Solution

by:
it_saige earned 500 total points
Comment Utility
Don't try to get the Cell from the DataGridView properties.  Rather uses what the event gives you to get the cell.  The event also gives you the FormattedValue of the cell that is validating.  Consider this example -

Form1.vb -
Imports System.ComponentModel

Public Class Form1
	Private IsLoading As Boolean = False

	Private ReadOnly Products As BindingList(Of Product) = New BindingList(Of Product)() From
	 {
	  New Product() With {.ID = 1, .ProductName = "Milk", .Price = "2.34"},
	  New Product() With {.ID = 2, .ProductName = "Bread", .Price = "1.19"},
	  New Product() With {.ID = 3, .ProductName = "Eggs", .Price = "2.18"},
	  New Product() With {.ID = 4, .ProductName = "Butter", .Price = "3.14"},
	  New Product() With {.ID = 5, .ProductName = "Chips", .Price = "3.48"},
	  New Product() With {.ID = 6, .ProductName = "Salsa", .Price = "4.22"},
	  New Product() With {.ID = 7, .ProductName = "Bacon", .Price = "5.13"},
	  New Product() With {.ID = 8, .ProductName = "Sausage", .Price = "2.99"},
	  New Product() With {.ID = 9, .ProductName = "Peanut Butter", .Price = "2.56"},
	  New Product() With {.ID = 10, .ProductName = "Jelly", .Price = "2.99"}
	 }

	Private Sub OnLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
		If Not IsLoading Then
			IsLoading = True
			DataGridSource.DataSource = Products
			DataGridView1.DataSource = DataGridSource
			IsLoading = False
		End If
	End Sub

	Private Sub OnCellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
		If Not IsLoading Then
			DataGridView1.Rows(e.RowIndex).ErrorText = ""

			If DataGridView1.Rows(e.RowIndex).IsNewRow Then Return

			If TypeOf DataGridView1.Columns(e.ColumnIndex) Is DataGridViewTextBoxColumn Then
				Dim tb As DataGridViewTextBoxColumn = DirectCast(DataGridView1.Columns(e.ColumnIndex), DataGridViewTextBoxColumn)

				If tb.Name.Equals(colQuantity.Name) Then
					Dim tempInteger As Integer

					If Not Integer.TryParse(e.FormattedValue.ToString(), tempInteger) Then
						e.Cancel = True
						DataGridView1.Rows(e.RowIndex).ErrorText = "The quantity must be an integer value."
					End If
				ElseIf tb.Name.Equals(colPrice.Name) Then
					Dim tempDecimal As Decimal

					If Not Decimal.TryParse(e.FormattedValue.ToString(), tempDecimal) OrElse tempDecimal < 0.0 Then
						e.Cancel = True
						DataGridView1.Rows(e.RowIndex).ErrorText = "The price must be a non-negative decimal value."
					End If
				End If
			End If
		End If
	End Sub

	Private Sub OnCellValidated(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValidated
		TextBox1.Text = Products.Sum(Function(item) item.SubTotal).ToString("C2")
	End Sub
End Class

Class Product
	Private fQuantity As Integer = 0
	Private fPrice As Decimal = 0.0
	Public Property ID() As Integer
	Public Property ProductName() As String

	Public Property Quantity() As Integer
		Get
			Return fQuantity
		End Get
		Set(ByVal value As Integer)
			If Not value.Equals(fQuantity) Then
				fQuantity = value
			End If
		End Set
	End Property

	Public Property Price() As Decimal
		Get
			Return fPrice
		End Get
		Set(ByVal value As Decimal)
			If Not value.Equals(fPrice) Then
				fPrice = value
			End If
		End Set
	End Property

	Public ReadOnly Property SubTotal() As Decimal
		Get
			Return Quantity * Price
		End Get
	End Property
End Class

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

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

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
		Me.components = New System.ComponentModel.Container()
		Me.DataGridView1 = New System.Windows.Forms.DataGridView()
		Me.colID = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colProductName = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colQuantity = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colPrice = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.colSubTotal = New System.Windows.Forms.DataGridViewTextBoxColumn()
		Me.ProductSource = New System.Windows.Forms.BindingSource(Me.components)
		Me.Label1 = New System.Windows.Forms.Label()
		Me.TextBox1 = New System.Windows.Forms.TextBox()
		Me.DataGridSource = New System.Windows.Forms.BindingSource(Me.components)
		CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
		CType(Me.ProductSource, System.ComponentModel.ISupportInitialize).BeginInit()
		CType(Me.DataGridSource, System.ComponentModel.ISupportInitialize).BeginInit()
		Me.SuspendLayout()
		'
		'DataGridView1
		'
		Me.DataGridView1.AllowUserToAddRows = False
		Me.DataGridView1.AllowUserToDeleteRows = False
		Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
		Me.DataGridView1.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {Me.colID, Me.colProductName, Me.colQuantity, Me.colPrice, Me.colSubTotal})
		Me.DataGridView1.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter
		Me.DataGridView1.Location = New System.Drawing.Point(13, 13)
		Me.DataGridView1.Name = "DataGridView1"
		Me.DataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
		Me.DataGridView1.Size = New System.Drawing.Size(566, 214)
		Me.DataGridView1.TabIndex = 0
		'
		'colID
		'
		Me.colID.DataPropertyName = "ID"
		Me.colID.HeaderText = "ID"
		Me.colID.Name = "colID"
		Me.colID.Visible = False
		'
		'colProductName
		'
		Me.colProductName.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill
		Me.colProductName.DataPropertyName = "ProductName"
		Me.colProductName.HeaderText = "Product Name"
		Me.colProductName.Name = "colProductName"
		Me.colProductName.ReadOnly = True
		Me.colProductName.Resizable = System.Windows.Forms.DataGridViewTriState.[True]
		Me.colProductName.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable
		'
		'colQuantity
		'
		Me.colQuantity.DataPropertyName = "Quantity"
		Me.colQuantity.HeaderText = "Quantity"
		Me.colQuantity.Name = "colQuantity"
		'
		'colPrice
		'
		Me.colPrice.DataPropertyName = "Price"
		Me.colPrice.HeaderText = "Price"
		Me.colPrice.Name = "colPrice"
		'
		'colSubTotal
		'
		Me.colSubTotal.DataPropertyName = "SubTotal"
		Me.colSubTotal.HeaderText = "SubTotal"
		Me.colSubTotal.Name = "colSubTotal"
		Me.colSubTotal.ReadOnly = True
		'
		'Label1
		'
		Me.Label1.AutoSize = True
		Me.Label1.Location = New System.Drawing.Point(434, 236)
		Me.Label1.Name = "Label1"
		Me.Label1.Size = New System.Drawing.Size(34, 13)
		Me.Label1.TabIndex = 1
		Me.Label1.Text = "Total:"
		'
		'TextBox1
		'
		Me.TextBox1.Location = New System.Drawing.Point(479, 233)
		Me.TextBox1.Name = "TextBox1"
		Me.TextBox1.ReadOnly = True
		Me.TextBox1.Size = New System.Drawing.Size(100, 20)
		Me.TextBox1.TabIndex = 2
		'
		'Form1
		'
		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
		Me.ClientSize = New System.Drawing.Size(591, 265)
		Me.Controls.Add(Me.TextBox1)
		Me.Controls.Add(Me.Label1)
		Me.Controls.Add(Me.DataGridView1)
		Me.Name = "Form1"
		Me.Text = "Form1"
		CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
		CType(Me.ProductSource, System.ComponentModel.ISupportInitialize).EndInit()
		CType(Me.DataGridSource, System.ComponentModel.ISupportInitialize).EndInit()
		Me.ResumeLayout(False)
		Me.PerformLayout()

	End Sub
	Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView
	Friend WithEvents Label1 As System.Windows.Forms.Label
	Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
	Friend WithEvents DataGridSource As System.Windows.Forms.BindingSource
	Friend WithEvents ProductSource As System.Windows.Forms.BindingSource
	Friend WithEvents colID As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colProductName As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colQuantity As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colPrice As System.Windows.Forms.DataGridViewTextBoxColumn
	Friend WithEvents colSubTotal As System.Windows.Forms.DataGridViewTextBoxColumn

End Class

Open in new window

Produces the following output -Initial startupAfter changing the quantity of milk.After changing the price of milk.Trying to change the price of milk to a negative number.-saige-
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now