Find rows with CheckBox checked DataGridView - vb.net

I put some code in to find what checkboxes have been checked in my DataGridView, but for some reason this isn't working.
I have looping through the rows in the DataGridView:
For Each row As DataGridViewRow In dgv_assets.Rows
Next
Then in here i have casted the first column as a DataGridViewCheckBoxCell:
For Each row As DataGridViewRow In dgv_assets.Rows
Dim chk As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
Next
Then I am checking for all the checkboxes that have been checked:
For Each row As DataGridViewRow In dgv_assets.Rows
Dim chk As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
If chk.Value = chk.TrueValue Then
MessageBox.Show("Checked")
End If
Next
For some reason even if the checkboxes are checked or unchecked they all hit the MessageBox.

Your code is almost correct, I guess the casting is the problem.
For Each row As DataGridViewRow In DataGridView1.Rows
Dim chk As DataGridViewCheckBoxCell = row.Cells(Column1.Name)
If chk.Value IsNot Nothing AndAlso chk.Value = True Then
MessageBox.Show("Checked: " + chk.RowIndex.ToString())
End If
Next
Column1 should be the column name of the DataGridViewCheckBoxCell that you are referring.

you can do in that simple way.
For i As Integer = 0 To dtg.RowCount - 1
If dtg.Item(0, i).Value = "True" Then
MsgBox("check")
End If
Next
I hope to be as helpful

Here is an example using a language extension method
Form level variable
Private Const CheckBoxColName As String = "Process"
Place the following in a code module, not a form or class
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function CheckBoxCount(ByVal GridView As DataGridView, ByVal ColumnIndex As Integer, ByVal Checked As Boolean) As Integer
Return (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where CBool(Rows.Cells(ColumnIndex).Value) = Checked).Count
End Function
Use the extension method using the private variable above, CheckBoxColName which is the name of the column in the DataGridView as a DataGridViewCheckBoxColumn
If DataGridView1.CheckBoxCount(CheckBoxColName, True) > 0 Then
Dim Rows = DataGridView1.GetCheckedRows1(CheckBoxColName)
For Each Row In Rows
Console.WriteLine(Row.Cells.Item(1).Value)
Next
End If
If you want to use column index rather than column name the following will do so
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function CheckBoxCount(ByVal GridView As DataGridView, ByVal ColumnIndex As Integer, ByVal Checked As Boolean) As Integer
Return (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where CBool(Rows.Cells(ColumnIndex).Value) = Checked).Count
End Function
Note both allow you to get check or un-checked.
The following gets the actual rows
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function GetCheckedRows1(ByVal GridView As DataGridView, ByVal ColumnName As String) As List(Of DataGridViewRow)
Dim Temp = (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where Not Rows.IsNewRow).ToList
Return (From SubRows In Temp Where CBool(SubRows.Cells(ColumnName).Value) = True).ToList
End Function

you must first verify that TrueValue not null , since according to the documentation , the default is null. And then check if true.
Here Doc : TrueValue

Add CheckBox with Name CK1 And Add DataGridView with Name Dgrd and must the first cell be DataGridViewCheckBoxCell And Add the code:
Private Sub CK1_CheckedChanged(sender As Object, e As EventArgs) Handles CK1.CheckedChanged
If CK1.Checked = True Then
Try
Dim I As Integer
For I = 0 To Dgrd.Rows.Count - 1
Dim CHKRow As DataGridViewCheckBoxCell = Dgrd.Rows(I).Cells(0)
If CHKRow.Value = False Then
CHKRow.Value = True
End If
Next
Catch ex As Exception
End Try
Else
Try
Dim I As Integer
For I = 0 To Dgrd.Rows.Count - 1
Dim CHKRow As DataGridViewCheckBoxCell = Dgrd.Rows(I).Cells(0)
If CHKRow.Value = True Then
CHKRow.Value = False
End If
Next
Catch ex As Exception
End Try
End If
End Sub

Related

DataGridView column of arbitrary controls per row (or replicate that appearance)

I have a DataGridView which contains, among other things, a "Feature" column and a "Value" column. The "Feature" column is a DataGridViewComboBoxColumn. What I would like to do, is manipulate the "Value" column, such that it can be one of a number of controls, depending on the item selected in the "Feature" column on any given row. So, for example :
Feature
Value Cell Behaviour
A
Combobox with a pre-determined set of options, specific to Feature A
B
Combobox with a different set of pre-determined options, specific to Feature B
C
Checkbox
D
Textbox (free-format)
X
etc. etc.
My initial naive approach to this (which I never really expected to work but figured I'd try anyway...) was to programmatically manipulate the specific value cell in the grid whenever the Feature combobox on the same row was changed :
Private Sub dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgv.CellValueChanged
Dim changedCell As DataGridViewCell = CType(dgv.Rows(e.RowIndex).Cells(e.ColumnIndex), DataGridViewCell)
If changedCell.ColumnIndex = cboFeatureColumn.Index Then
Dim cboChangedFeature = CType(changedCell, DataGridViewComboBoxCell)
If cboChangedFeature.Value IsNot Nothing Then ConfigureValueField(cboChangedFeature)
End If
End Sub
Private Sub ConfigureValueField(cboFeature As DataGridViewComboBoxCell)
Dim cllValueField As DataGridViewCell = dgv.Rows(cboFeature.RowIndex).Cells(valueColumn.Index)
Dim featureID As Integer = dgv.Rows(cboFeature.RowIndex).Cells(featureIDColumn.Index).Value
Dim matches = From row In dtbFeatureList Let lookupID = row.Field(Of Integer)("ID") Where lookupID = featureID
Dim strFieldControl As String = ""
If matches.Any Then strFeatureControl = matches.First().row.Field(Of String)("FieldControl")
Select Case strFieldControl
Case "Checkbox"
' Do something
Case "Textbox"
' Do something
Case "Combobox"
Dim cboConfigured As New DataGridViewComboBoxCell
Dim dvOptions As New DataView(dtbFeatureValueList)
dvOptions.RowFilter = "[FeatureID] = " & featureID
Dim dtbOptions As DataTable
dtbOptions = dvOptions.ToTable
With cboConfigured
.DataSource = dtbOptions
.ValueMember = "Value"
.DisplayMember = "ValueText"
.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox
.ReadOnly = False
End With
cllValueField = cboConfigured
End Select
End Sub
But this (probably, obviously to many) doesn't work; for starters it throws a DataError Default Error Dialog :
The following exception occurred in the DataGridView:
System.FormatException: DataGridViewComboBoxCell value is not valid To
replace this default dialog please handle the DataError event.
...which I can trap and handle (i.e. ignore!) easily enough :
Private Sub dgv_DataError(sender As Object, e As DataGridViewDataErrorEventArgs) Handles dgv.DataError
e.Cancel = True
End Sub
...and the resulting cell does have the appearance of a combobox but nothing happens when I click the dropdown (no list options appear) I suspect there are a whole host of DataErrors being thrown; to be quite honest, I'm not entirely comfortable with ignoring exceptions like this without handling them properly...
The only alternative option I can think of is to add separate columns for each possible value type (so add a DataGridViewComboBoxColumn for combos, a DataGridViewCheckBoxColumn for checkboxes, a DataGridViewTextBoxColumn for textboxes etc.) but then all of my values are scattered across multiple columns instead of all under a single heading which will be really confusing to look at.
And I really want to retain the appearance of comboboxes (set list of options) versus checkboxes (boolean values) versus textboxes (free-format text), as it makes it a lot easier for users to differentiate the values.
I read somewhere that it may be possible to derive my own custom column class, inheriting the native DataGridViewColumn class, but I couldn't find any examples of how this was done. I've done something similar with a customised DataGridViewButtonColumn but literally just to change the appearance of the buttons across the entire column, not the functionality of the individual cells within it.
Would anybody have any suggestions as to how it might be possible to have a mix of controls in the same column, configured specifically to the row in which they reside?
EDIT
So, I followed the walkthrough at : https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-host-controls-in-windows-forms-datagridview-cells?view=netframeworkdesktop-4.8&redirectedfrom=MSDN
And I've added four new classes to my project as follows :
UserControl class : a basic control which contains a textbox, a combobox and a checkbox, and basic methods for showing/hiding each one as appropriate, configuring the combobox if necessary etc. By default, the UserControl should display as an empty textbox.
CustomConfigurableCellEditingControl : derived from the UserControl in #1
DataGridViewCustomConfigurableCell : container for the EditingControl in #2 and derived from DataGridViewTextBoxCell
DataGridViewCustomConfigurableColumn : container for the Cell in #3 and derived from DataGridViewColumn
Public Class UserControl
Private displayControl As String
Private displayValue As String
Private myValue As String
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
displayControl = "Textbox"
displayValue = ""
refreshDisplay()
End Sub
Public Property ControlToDisplay As String
Get
Return displayControl
End Get
Set(value As String)
displayControl = value
End Set
End Property
Public Property ValueToDisplay As String
Get
Return displayValue
End Get
Set(value As String)
displayValue = value
End Set
End Property
Public Property Value As String
Get
Return myValue
End Get
Set(value As String)
myValue = value
End Set
End Property
Public Sub refreshDisplay()
Select Case displayControl
Case "Textbox"
With ucTextBox
.Text = displayValue
.Visible = True
End With
ucComboBox.Visible = False
ucCheckbox.Visible = False
Case "Combobox"
With ucComboBox
.Visible = True
End With
ucTextBox.Visible = False
ucCheckbox.Visible = False
Case "Checkbox"
With ucCheckbox
.Checked = myValue
.Visible = True
End With
ucTextBox.Visible = False
ucComboBox.Visible = False
End Select
End Sub
Public Sub configureCombobox(dtb As DataTable, valueMember As String, displayMember As String, style As ComboBoxStyle)
With ucComboBox
.DataSource = dtb
.ValueMember = "ID"
.DisplayMember = "FriendlyName"
.DropDownStyle = style
End With
End Sub
End Class
Class CustomConfigurableCellEditingControl
Inherits UserControl
Implements IDataGridViewEditingControl
Private dataGridViewControl As DataGridView
Private valueIsChanged As Boolean = False
Private rowIndexNum As Integer
Public Sub New()
End Sub
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
'Return Me.Value.ToShortDateString()
Return Me.valueIsChanged.ToString
End Get
Set(ByVal value As Object)
Me.Value = value
End Set
End Property
Public Function GetEditingControlFormattedValue(ByVal context As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.valueIsChanged.ToString
End Function
Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As DataGridViewCellStyle) _
Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
End Sub
Public Property EditingControlRowIndex() As Integer _
Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return rowIndexNum
End Get
Set(ByVal value As Integer)
rowIndexNum = value
End Set
End Property
Public Function EditingControlWantsInputKey(ByVal key As Keys,
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
End Function
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
' No preparation needs to be done.
End Sub
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean _
Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
Public Property EditingControlDataGridView() As DataGridView _
Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return dataGridViewControl
End Get
Set(ByVal value As DataGridView)
dataGridViewControl = value
End Set
End Property
Public Property EditingControlValueChanged() As Boolean _
Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return valueIsChanged
End Get
Set(ByVal value As Boolean)
valueIsChanged = value
End Set
End Property
Public ReadOnly Property EditingControlCursor() As Cursor _
Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
Protected Overrides Sub OnValueChanged(ByVal eventargs As EventArgs)
' Notify the DataGridView that the contents of the cell have changed.
valueIsChanged = True
Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)
MyBase.OnValueChanged(eventargs)
End Sub
End Class
Public Class DataGridViewCustomConfigurableCell
Inherits DataGridViewTextBoxCell
Public Sub New()
End Sub
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer,
ByVal initialFormattedValue As Object,
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
' Set the value of the editing control to the current cell value.
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
Dim ctl As CustomConfigurableCellEditingControl = CType(DataGridView.EditingControl, CustomConfigurableCellEditingControl)
' Use the default row value when Value property is null.
If (Me.Value Is Nothing) Then
ctl.Value = CType(Me.DefaultNewRowValue, String)
Else
ctl.Value = CType(Me.Value, String)
End If
End Sub
Public Overrides ReadOnly Property EditType() As Type
Get
' Return the type of the editing control that Cell uses.
Return GetType(CustomConfigurableCellEditingControl)
End Get
End Property
Public Overrides ReadOnly Property ValueType() As Type
Get
' Return the type of the value that Cell contains.
Return GetType(String)
End Get
End Property
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
Return ""
End Get
End Property
End Class
Imports System.Windows.Forms
Public Class DataGridViewCustomConfigurableColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New DataGridViewCustomConfigurableCell())
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a Custom Configurable Cell.
If (value IsNot Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(DataGridViewCustomConfigurableCell)) Then
Throw New InvalidCastException("Must be a Custom Configurable Cell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
But... I'm still none the wiser as to how I populate, display, manipulate etc. The code compiles fine, but I just get a blank column. I can't see any controls, I can't see any values and I can't seem to "trap" any of the events that should manipulate them?
With dgv
cfgValueColumn = New DataGridViewCustomConfigurableColumn With {.DisplayIndex = valueColumn.Index + 1}
With cfgValueColumn
.HeaderText = "Custom Value"
.Width = 300
End With
.Columns.Add(cfgValueColumn)
Dim cfgCell As DataGridViewCustomConfigurableCell
For Each row As DataGridViewRow In .Rows
cfgCell = CType(row.Cells(cfgValueColumn.Index), DataGridViewCustomConfigurableCell)
With cfgCell
.Value = row.Cells(valueColumn.Index).Value
End With
Next
End With
Your main approach is correct if you just need to change the type of the given cell based on the ComboBox selection.
When the value changes of the ComboBox cell:
Dispose of the current cell of the target column.
Create a new cell whose type is defined by the ComboBox selection.
Assign the new cell to the grid place of the old one.
Here's a working example.
Private Sub dgv_CellValueChanged(
sender As Object,
e As DataGridViewCellEventArgs) Handles dgv.CellValueChanged
If e.RowIndex < 0 Then Return
If e.ColumnIndex = dgvcTypeSelector.Index Then
Dim cmb = DirectCast(dgv(e.ColumnIndex, e.RowIndex), DataGridViewComboBoxCell)
Dim selItem = cmb.FormattedValue.ToString()
Dim valSelCell = dgv(dgvcValueSelector.Index, e.RowIndex)
valSelCell.Dispose()
Select Case selItem
Case "Text"
valSelCell = New DataGridViewTextBoxCell With {
.Value = "Initial value If any."
}
Case "Combo"
valSelCell = New DataGridViewComboBoxCell With {
.ValueMember = "Value",
.DisplayMember = "ValueText",
.DataSource = dt,
.Value = 2 ' Optional...
}
Case "Check"
valSelCell = New DataGridViewCheckBoxCell With {
.ValueType = GetType(String),
.Value = True
}
valSelCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
Case "Button"
valSelCell = New DataGridViewButtonCell With {
.Value = "Click Me!"
}
valSelCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
End Select
dgv(dgvcValueSelector.Index, e.RowIndex) = valSelCell
ElseIf e.ColumnIndex = dgvcValueSelector.Index Then
Dim cell = dgv(e.ColumnIndex, e.RowIndex)
Console.WriteLine($"{cell.Value} - {cell.FormattedValue}")
End If
End Sub
Private Sub dgv_CurrentCellDirtyStateChanged(
sender As Object,
e As EventArgs) Handles dgv.CurrentCellDirtyStateChanged
If dgv.IsCurrentCellDirty Then
dgv.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
' If you need to handle the Button cells.
Private Sub dgv_CellContentClick(
sender As Object,
e As DataGridViewCellEventArgs) Handles dgv.CellContentClick
If e.RowIndex >= 0 AndAlso
e.ColumnIndex = dgvcValueSelector.Index Then
Dim btn = TryCast(dgv(e.ColumnIndex, e.RowIndex), DataGridViewButtonCell)
If btn IsNot Nothing Then
Console.WriteLine(btn.FormattedValue)
End If
End If
End Sub
Note, I've changed the value type of the check box cell by ValueType = GetType(String) to avoid throwing exceptions caused by the different value types of the check box and main columns. I'd assume the main column here is of type DataGridViewTextBoxColumn. So you have String vs. Boolean types. If you face problems in the data binding scenarios, then just swallow the exception.
Private Sub dgv_DataError(
sender As Object,
e As DataGridViewDataErrorEventArgs) Handles dgv.DataError
If e.RowIndex >= 0 AndAlso e.ColumnIndex = dgvcValueSelector.Index Then
e.ThrowException = False
End If
End Sub

Check the item in ToolStripMenuItem dynamically through Sub Function

I am new to .Net Visual Basic, I am currently self learning and trying to make some small application.
I need a help on Checking a sub menu item of ToolStripMenuItem
Complete concept is like:
I have a datagridview in which user will be able to rearrange the column or make a column visible or Hidded for this I have Sub / Function like below:
Public Sub Fun_Grid_Colomn_Visibility(ByVal GridName As DataGridView, ByRef ColName As String, ByVal MS_col As ToolStripMenuItem, ChkVal As Boolean)
If ChkVal = True Then
With GridName
.Columns("" & ColName & "").Visible = False
End With
MS_col.Checked = False
Exit Sub
End If
If ChkVal = False Then
GridName.Columns("" & ColName & "").Visible = True
MS_col.Checked = True
Exit Sub
End If
End Sub
On the form close I will be saving the user grid format as below (Got code from another Q/A Post) :
Public Sub WriteGrideViewSetting(ByVal dgv As DataGridView, ByVal FileName As String)
Dim settingwriter As XmlTextWriter = New XmlTextWriter("C:\Users\<username>\Desktop\temp\" & FileName & ".xml", Nothing)
settingwriter.WriteStartDocument()
settingwriter.WriteStartElement(dgv.Name)
Dim count As Integer = dgv.Columns.Count
For i As Integer = 0 To count - 1
settingwriter.WriteStartElement("column")
settingwriter.WriteStartElement("Name")
settingwriter.WriteString(dgv.Columns(i).Name)
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("width")
settingwriter.WriteString(dgv.Columns(i).Width.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("headertext")
settingwriter.WriteString(dgv.Columns(i).HeaderText)
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("displayindex")
settingwriter.WriteString(dgv.Columns(i).DisplayIndex.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("visible")
settingwriter.WriteString(dgv.Columns(i).Visible.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteEndElement()
Next
settingwriter.WriteEndElement()
settingwriter.WriteEndDocument()
settingwriter.Close()
End Sub
End Module
If the user is reopening the form I used the below (Q/A code) to rearrange Datagridview column as pervious :
Public Sub ReadDataGridViewSetting(ByVal dgv As DataGridView, ByVal FileName As String, ByRef Frm_name As Form)
Dim xmldoc As XmlDocument = New XmlDocument()
Dim xmlnode As XmlNodeList
Dim CMSN_ToolName As String
Dim Var_file_Chk As String = "C:\Users\<user>\Desktop\temp\" & FileName & ".xml"
If System.IO.File.Exists(Var_file_Chk) = True Then
Dim fs As FileStream = New FileStream(Var_file_Chk, FileMode.Open, FileAccess.Read)
xmldoc.Load(fs)
xmlnode = xmldoc.GetElementsByTagName("column")
For i As Integer = 0 To xmlnode.Count - 1
Dim columnName As String = xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
Dim width As Integer = Integer.Parse(xmlnode(i).ChildNodes.Item(1).InnerText.Trim())
Dim headertext As String = xmlnode(i).ChildNodes.Item(2).InnerText.Trim()
Dim displayindex As Integer = Integer.Parse(xmlnode(i).ChildNodes.Item(3).InnerText.Trim())
Dim visible As Boolean = Convert.ToBoolean(xmlnode(i).ChildNodes.Item(4).InnerText.Trim())
dgv.Columns(columnName).Width = width
dgv.Columns(columnName).HeaderText = headertext
dgv.Columns(columnName).DisplayIndex = displayindex
dgv.Columns(columnName).Visible = visible
Next
fs.Close()
End If
End Sub
Now what I need is that a Function or Sub for the Itemmenu. If a Particular column is Visible in the datagridview then the particular Itemmenu should be checked else it would be unchecked. I need this function when Itemmenu is being displayed / opened.
what I tried just (for sample) in Itemmenu opening is like
Private Sub ColumnsToolStripMenuItem_DropDownOpening(sender As Object, e As EventArgs) Handles ColumnsToolStripMenuItem.DropDownOpening
If DGV_CompList.Columns("DGC_Est").Visible = True Then
Dim CMSN_ToolName = MS_CV_Est.Name
Dim unused As ToolStripMenuItem = New ToolStripMenuItem(CMSN_ToolName) With {
.Checked = True
}
End If
End Sub
DGV_CompList -> DataGridView
DGC_Est -> Column Name of datagridview
MS_CV_Est -> - ToolStripMenuItem which need to checked
(Note: I will be changing the MenuItem Name to Match Datagrid Column name for Sync)
But the ToolStripMenuItem is not getting checked.
Actually I need function / Sub where I will be able to pass the grid name and the Menuname and loop through the grid columns and check if the column is visible or not if the particular column is visible then I need to check that item in the itemmenu.
I am requesting for the sub / function because it can be used for any toolstripmenuitem in any form.
Thanks and Regards.
As per #Jimi's hint, assigned each required Menuitem's Tag property with the datagridview column name and created the below sub / function :
Public Sub Fun_ToolStripMenuItem_Check(ByVal dgv As DataGridView, ByVal TS_Menu_Items As ToolStripItemCollection)
For Each item As ToolStripMenuItem In TS_Menu_Items.OfType(Of ToolStripMenuItem)
If Not item.Tag = "" Then
If dgv.Columns(item.Tag).Visible = True Then
item.Checked = True
Else
item.Checked = False
End If
End If
For Each submenu_item As ToolStripMenuItem In item.DropDownItems.OfType(Of ToolStripMenuItem)
If Not submenu_item.Tag = "" Then
If dgv.Columns(submenu_item.Tag).Visible = True Then
submenu_item.Checked = True
Else
submenu_item.Checked = False
End If
End If
Next
Next
End Sub
Note in the loop used - " OfType(Of ToolStripMenuItem) " because I have ToolStripSeparator between the Itemmenus.
On mouse over called the Sub by :
Private Sub MS_ColumnVisible_DropDownOpening(sender As Object, e As EventArgs) Handles MS_ColumnVisible.DropDownOpening
Fun_ToolStripMenuItem_Check(DGV_CompList, MS_CompDGV.Items)
End Sub
'DGV_CompList' - Datagridview Name and 'MS_CompDGV' - ContextMenuStrip Name
More important is that I did not assign any value to the Tag property to Menuitems which are not used show or hide the datagridview columns.

VB.NET load Datagridview thrown exception while calling it from different thread

Firstly sorry for my bad English.
My problem is when I'm load data from different thread cause "Object reference not set to an instance of an object."
Here is my code :
Private Sub GetData(ByVal startRecord As Integer, ByVal maxRecord As Integer)
Dim ds As DataSet = New DataSet()
Dim da As MySqlDataAdapter = New MySqlDataAdapter("select * from my_data", SqlCon)
Try
da.Fill(ds, startRecord, maxRecord, "my_data")
ds.Tables("my_data").DefaultView.AllowNew = False
dgv.DataSource = ds.Tables("my_data")
For Each col As Object In dgv.Columns
If TypeOf col Is DataGridViewCheckBoxColumn Then
DirectCast(col, DataGridViewCheckBoxColumn).Visible = False
ElseIf TypeOf col Is DataGridViewImageColumn Then
DirectCast(col, DataGridViewImageColumn).Visible = False
ElseIf TypeOf col Is DataGridViewTextBoxColumn Then
Dim tbc As DataGridViewTextBoxColumn = CType(col, DataGridViewTextBoxColumn)
If tbc.Name = "no" Then
tbc.Width = 40
tbc.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
tbc.HeaderText = "No"
ElseIf tbc.Name = "ID" Then
tbc.Width = 110
tbc.HeaderText = "ID"
ElseIf tbc.Name = "name" Then
tbc.Width = 290
tbc.HeaderText = "Name"
ElseIf tbc.Name = "Address" Then
tbc.Width = 230
tbc.HeaderText = "Address"
Else
tbc.Visible = False
End If
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
The problem is here :
dgv.DataSource = ds.Tables("my_data")
So, what's wrong with my codes? It's always getting error when calling it from multithreading method, but when i put in on the button it's work fine.
It's always getting error when calling it from multithreading method,
but when i put in on the button it's work fine.
Your GetData() method is obviously not located in your Form, so it has no idea who "dgv" is. One solution would be to pass the DataGridView just like your other parameters.
Change:
Private Sub GetData(ByVal startRecord As Integer, ByVal maxRecord As Integer)
To:
Private Sub GetData(ByVal dgv As DataGridView, ByVal startRecord As Integer, ByVal maxRecord As Integer)
Then the call (in your Form) would look like this:
GetData(dgv, someValue, someOtherValue)
what vb is saying to you is that the variable you are trying to use hasn't nothing in it. you need to set it to point at something.
no where in your code have you specified what dvg is and you haven't carried the dvg over into the subroutine.
so you should have dim dvg as something = something or dim dvg as new something = new something

Don't Add Value If Already Exists In Datagridview

I have a "table_info" table with a column for ID,NAME
When Adding new ID,Name. I would like to check if it's already exists. and If it exists, produce a MessageBox.
How can this be done
Ypu have to refer to use rowCell_ID as string because it is the column name in your datagridivew:
Function IsInDatagridview(ByVal cell1 As String, ByVal cell2 As String, ByVal rowCell1_ID As Integer, ByVal rowCell2_ID As Integer, ByRef dgv As DataGridView)
Dim isFound As Boolean = False
For Each rw As DataGridViewRow In dgv.Rows
If rw.Cells("rowCell1_ID" ).Value.ToString = cell1 Then
If rw.Cells("rowCell2_ID" ).Value.ToString = cell2 Then
isFound = True
Return isFound
End If
End If
Next
Return isFound
End Function
There is more than one way to accomplish this. You could check the datasource/set or the actual datagridview itself, if you don't have too many rows. If it's the later then you could do it like so:
Check Function returned true if the criteria is met:
Function IsInDatagridview(ByVal cell1 As String, ByVal cell2 As String, ByVal rowCell1_ID As Integer, ByVal rowCell2_ID As Integer, ByRef dgv As DataGridView)
Dim isFound As Boolean = False
For Each rw As DataGridViewRow In dgv.Rows
If rw.Cells(rowCell1_ID ).Value.ToString = cell1 Then
If rw.Cells(rowCell2_ID ).Value.ToString = cell2 Then
isFound = True
Return isFound
End If
End If
Next
Return isFound
End Function
.
Then to use the Function to display a MessageBox if the criteria is met:
If (IsInDatagridview("id", "name", 0, 1, DataGridView1)) Then
''// Code to display message.
MsgBox("Record Exists!", MsgBoxStyle.Information)
End If
You may need to change The ID to an integer but I reckon it should work. Haven't tested it.
Okay so what this will do is iterate through each row 'rw' within the datagridview you specify, checking for String matches of the cell's columns' and if a match is found 'isFound' is set to true then 'isFound' is returned.

Using string as object name

I'm trying to use string as object name. Example I have an object and has a name = Label1. Can I do this?
Dim i As String = "Label1"
someVariable = i.Text
I'm using string as object name, is it possible?
You could iterate over all of the controls as #Christian Sauer said but you might run into problems if any controls are containers of controls. You'd need to do a recursive search to solve that. However, the ControlCollection actually has a Find() method that you can use. It returns an array of controls that match the name and optionally performs a recursive search.
''//Our final control
Dim someVariable As Control = Nothing
''//Search recursively for our control
Dim SearchedControls = Me.Controls.Find(key:="Label1", searchAllChildren:=True)
''//If we found one and only one control
If SearchedControls.Count = 1 Then
''//Set it to our variable
someVariable = SearchedControls(0)
Else
''//Whatever your logic dictates here
End If
This is not possible - but what you can do:
Dim i As String = "Label1"
Dim Obj as Label
for each elem in me.controls
if elem.Name = i then
Obj = elem
exit for
end if
next
someVariable = obj.Text
I am iterating over all WinForms control to find the label with the Name "Label1" - when found, i assign the label to a Variable.
This works, but can be quite dangerous, especially if you add controls
I know it's been answered, but this is from my library, and I use it all the time. It will iterate over all controls, and containers' controls recursively as #ChrisHaas suggested.
Public Function GetControlByName(ByRef parent As Control, ByVal name As String) As Control
For Each c As Control In parent.ChildControls
If c.Name = name Then
Return c
End If
Next
Return Nothing
End Function
<Extension()> _
Public Function ChildControls(ByVal parent As Control) As ArrayList
Return ChildControls(Of Control)(parent)
End Function
<Extension()> _
Public Function ChildControls(Of T)(ByVal parent As Control) As ArrayList
Dim result As New ArrayList()
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is T Then result.Add(ctrl)
result.AddRange(ChildControls(Of T)(ctrl))
Next
Return result
End Function
(It's been asked and answered before)
Loop Through Controls on Web User Control
I'm sure it's answered but some points to be clear it's control array and result so as to be sure it's corrected.
Private Sub btn1_click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn1.Click
Dim Ds As New DataSet
Dim str As String = ""
str = " SELECT TOP (10) t_Suppliers.STNo from t_Suppliers "
Ds = SqlHelper.ExecuteDataset(ConnectionString, CommandType.Text, str)
For i As Integer = 0 To Ds.Tables(0).Rows.Count - 1
Dim str1 As String = "lblInv" & i + 1
Dim OBj As New Label
Try
Dim SearchedControls() As Control = Me.Controls.Find(key:=str1, searchAllChildren:=True)
If SearchedControls.Length > 0 Then
SearchedControls(0).Text = Ds.Tables(0).Rows(i).Item("STNo").ToString
End If
Catch
End Try
Next
End Sub
I found the following solution on another site.
It works.
--Quote -
Dim TextBox As TextBox
Dim I As Integer = 2
Dim name As String = "TextBox" & I.ToString
TextBox = Me.Controls.Item(name)
TextBox.Text = "Something special"