I have a DataGridView (called DataGridViewSecurity) in VB.net (Visual Studio 2010) which is bound to a DataTable (called DataTableSecurity) in a DataSet (called DataSetSecurity). I have added a nonbound column (called nSecurityComboBox) that I set based on an integer field (called nSecLevel) in the DataTable. After setting the combobox, it doesn't display anything in the combobox, but when you select the combobox, the 5 values in it's items collection show.
Here's the code I'm using to add a record to the DataTable and then to set the combobox:
Sub Foo()
.
.
.
DataSetSecurity.Tables(0).Rows.Add(New Object() {sName, sID, sSec})
ComboCell_Select(nRow, 3, DataGridViewSecurity, sSecRecs.nSecLevel)
MessageBox.Show("Value for the combo set at " + DataGridViewSecurity.Rows(nRow).Cells(3).Value.ToString)
.
.
.
End Sub
Private Sub ComboCell_Select(ByVal dgvRow As Integer, _
ByVal dgvCol As Integer, _
ByRef DGV As DataGridView,
ByRef nComboBoxRow As Int16)
Try
Dim CBox As DataGridViewComboBoxCell = CType(DGV.Rows(dgvRow).Cells(dgvCol), DataGridViewComboBoxCell)
Dim CCol As DataGridViewComboBoxColumn = CType(DGV.Columns(dgvCol), DataGridViewComboBoxColumn)
CBox.Value = CCol.Items(nComboBoxRow)
DGV.UpdateCellValue(dgvCol, dgvRow)
'MessageBox.Show("New value in the combo box = " + CBox.Value.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
The messagebox.show in Foo shows the correct value for the combobox, but nothing is displayed.
Anyone see what I'm doing wrong?
Thanks.
-NCGrimbo
In the end, I found some C# code that I converted to VB.net to fix the issue. Here's the code:
Private Sub DataGridViewSecurity_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridViewSecurity.EditingControlShowing
Dim cellComboBox As ComboBox = TryCast(e.Control, ComboBox)
If cellComboBox IsNot Nothing Then
' make sure the handler doen't get registered twice
RemoveHandler cellComboBox.SelectionChangeCommitted, AddressOf Me.CellComboBoxOnSelectionChangeCommitted
AddHandler cellComboBox.SelectionChangeCommitted, AddressOf Me.CellComboBoxOnSelectionChangeCommitted
End If
End Sub
Private Sub CellComboBoxOnSelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
Dim comboBox As DataGridViewComboBoxEditingControl = TryCast(sender, DataGridViewComboBoxEditingControl)
If sender Is Nothing Then
Return
End If
If comboBox.SelectedItem Is Nothing Then
Return
End If
If Me.DataGridViewSecurity.CurrentCell.Value = comboBox.SelectedItem Then
Return
End If
Me.DataGridViewSecurity.CurrentCell.Value = comboBox.SelectedItem
End Sub
If I understand the question right, all values are in the combobox just not being selected by default properly? I think I just had this problem a few days ago, here's what I have now.
'Create the combobox column
Dim comboBox As New DataGridViewComboBoxColumn()
'Add some stuff to the combobox
comboBox.Items.Add("FirstItem")
comboBox.Items.Add("SecondItem")
'Select the first item
comboBox.DefaultCellStyle.NullValue = comboBox.Items(0)
'Now add the whole combobox to the DataGridView
dgvItems.Columns.Add(comboBox)
Hope this helps!
Related
My problem:
I have a checkbox I use to control if certain textboxes are enabled or not, and I need to do this around 30+ times. I've named my textboxes numerically/sequentially (TB_name_1, TB_name_2, etc) so if I know the Checkbox name I know which textboxes are affected.
My question:
Can I make a class for my checkboxes that says "if this box is checked/unchecked, then enable/disable these 3 textboxes" without the class also having to be told which textboxes (finds them itself)?
Here's the copy/paste code I'm currently using (not a class, obviously). I change the first 2 values and the rest of the code solves itself. (PS - I see you laughing)
Private Sub T1_cb_c_1_CheckedChanged(sender As Object, e As EventArgs) Handles T1_cb_c_1.CheckedChanged
'change here for current checkbox
Dim b As CheckBox = T1_cb_c_1
'change here for start value of first textbox (of 3), the next 2 will be in sequence
Dim a As Integer = 1
'How much of the below code can be moved to, and controlled from, a class?
Dim a1 As Integer = a + 1
Dim a2 As Integer = a + 2
Dim TB_PtNum As TextBox = Me.Controls.Find("T1_tb_c_" & a, True).FirstOrDefault
Dim TB_Qty As TextBox = Me.Controls.Find("T1_tb_c_" & a1, True).FirstOrDefault
Dim TB_Seq As TextBox = Me.Controls.Find("T1_tb_c_" & a2, True).FirstOrDefault
If b.Checked = True Then
TB_PtNum.Enabled = True
TB_Qty.Enabled = True
TB_Seq.Enabled = True
Else
TB_PtNum.Enabled = False
TB_Qty.Enabled = False
TB_Seq.Enabled = False
End If
End Sub
Here's a design time only class that will do this. You only have to the AssociatedCheckbox property in the designer:
Public Class TextBoxWithCheckboxProperty
Inherits TextBox
Private m_CheckBox As CheckBox
Public Property AssociatedCheckBox As CheckBox
Get
Return m_CheckBox
End Get
Set(value As CheckBox)
If Not m_CheckBox Is Nothing Then
RemoveHandler m_CheckBox.CheckedChanged, AddressOf OnCheckBoxChanged
End If
m_CheckBox = value
If Not value Is Nothing Then
AddHandler m_CheckBox.CheckedChanged, AddressOf OnCheckBoxChanged
End If
OnCheckBoxChanged(m_CheckBox, Nothing)
End Set
End Property
Private Sub OnCheckBoxChanged(ByVal sender As Object, ByVal e As System.EventArgs)
If Not sender Is Nothing Then
Me.Enabled = CType(sender, CheckBox).Checked
Else
Me.Enabled = False
End If
End Sub
End Class
Here's a sample Form1 that uses it:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
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.CheckBox1 = New System.Windows.Forms.CheckBox()
Me.TextBoxWithCheckboxProperty1 = New WindowsApp4.TextBoxWithCheckboxProperty()
Me.SuspendLayout()
'
'CheckBox1
'
Me.CheckBox1.AutoSize = True
Me.CheckBox1.Location = New System.Drawing.Point(293, 131)
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox1.Size = New System.Drawing.Size(81, 17)
Me.CheckBox1.TabIndex = 0
Me.CheckBox1.Text = "CheckBox1"
Me.CheckBox1.UseVisualStyleBackColor = True
'
'TextBoxWithCheckboxProperty1
'
Me.TextBoxWithCheckboxProperty1.AssociatedCheckBox = Me.CheckBox1
Me.TextBoxWithCheckboxProperty1.Location = New System.Drawing.Point(428, 131)
Me.TextBoxWithCheckboxProperty1.Name = "TextBoxWithCheckboxProperty1"
Me.TextBoxWithCheckboxProperty1.Size = New System.Drawing.Size(100, 20)
Me.TextBoxWithCheckboxProperty1.TabIndex = 1
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBoxWithCheckboxProperty1)
Me.Controls.Add(Me.CheckBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents CheckBox1 As CheckBox
Friend WithEvents TextBoxWithCheckboxProperty1 As TextBoxWithCheckboxProperty
End Class
I would use the property Tag for the related controls.
Suppose to set this property to the value "line1" for the first set of textboxes and on the checkbox that controls them.
Next row of controls (checkbox+textboxes) will have the property set to "line2" and so on until the last row. (You can do this through the Winforms Designer or through code)
At this point you could have a single event handler for all your checkboxes
Private Sub onCheckedChanged(sender As Object, e As EventArgs) _
Handles T1_cb_c_1.CheckedChanged, T2_cb_c_2.CheckedChanged, _
..... add other checkbox events here .......
' Get whatever checkbox has been clicked and extract its tag
Dim b As CheckBox = DirectCast(sender, CheckBox)
Dim tag = b.Tag.ToString()
' Find the textbox controls in this form with the same Tag
Dim ctrls = Me.Controls.OfType(Of TextBox).Where(Function(x) x.Tag.ToString() = tag)
' Enabled status matches the status of the Checked property
For Each c as TextBox in ctrls
c.Enabled = b.Checked
Next
End Sub
I have been tasked with creating a cinema booking system in VB.net by my teacher. So far I have created 50 CheckBoxes and I am trying to rename them all to seat (number). I have this code in my Form1.load but it is not working because it is a type and not an expression. I tried using a variable for this but it did not work.
Here is my code:
For count As Integer = 1 To 54 Step 1
CheckBox(count).text = "Seat " & count
Next
Please help, and or recommend me another way to accomplish this.
set the name of the checkbox when you create it. To find out how to create a checkbox programmatically add a checkbox to a form then look at .designer.vb
dim cb as new checkbox
cb.name = "1"
cb.text = "Seat 1"
you need to also add the location and other properties
If you have already created your textboxes with names like 1, 2 then iterate through and get the numbers like this: If you call them CB_1 then cut the CB_ off before looking for the number.
dim cbNumber as int16
For Each c As Control In myContainer.Controls
If c.GetType() Is GetType(CheckBox) Then
cbnumber = cint(c.name)
c.text = "Seat" & cbnumber
End If
Next
Well, here's my approach. In order to test just drop on a FlowLayoutPanel, a Button, and a NumericUpDownonto the form.
Option Strict On
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For count As Integer = 1 To 54 Step 1
' Make a new CheckBox
Dim chkBox As New CheckBox()
' Setup the Checkbox
With chkBox
.Tag = count.ToString
.Name = CStr("seatCheckBox" & count.ToString)
.Text = String.Format("Seat {0}", count)
.ThreeState = False
.Checked = False
End With
' add an event listener for the checkbox checkstate changed event
AddHandler chkBox.CheckStateChanged, AddressOf Me.CheckBox_CheckStateChanged
' Add the checkbox to the control
Me.FlowLayoutPanel1.Controls.Add(chkBox)
' Keep the user from picking something that doesn't exist
Me.NumericUpDown1.Maximum = CDec(count)
Next
' Add and event listener for the find button click event
AddHandler Button1.Click, AddressOf Me.FindButton_Clicked
End Sub
' Find the checkbox in the form and return it
Private Function GetCheckBox(ByVal seatNumber As Integer) As CheckBox
Dim chkbox As CheckBox
' Try to find the Checkbox
Try
chkbox = TryCast(Me.Controls.Find(CStr("seatCheckBox" & seatNumber.ToString), True).First, CheckBox)
Catch ex As Exception
chkbox = Nothing
End Try
'Check if the trycast worked
If IsNothing(chkbox) Then
Throw New ArgumentOutOfRangeException("seatNumber", "The seat number to be searched for was not found")
Else
Return chkbox
End If
End Function
' Handle the Chekbox checkState event.
Private Sub CheckBox_CheckStateChanged(sender As Object, e As EventArgs)
' Convert to Checkbox
Dim chkBox As CheckBox = DirectCast(sender, CheckBox)
' Simple result string
Dim resultstring As String = CStr("Seat Number {0} is now {1}.")
' Set the values
Select Case chkBox.Checked
Case True
resultstring = String.Format(resultstring, chkBox.Tag, "taken")
Case False
resultstring = String.Format(resultstring, chkBox.Tag, "available")
End Select
' Display it
MsgBox(resultstring)
End Sub
Private Sub FindButton_Clicked(sender As Object, e As EventArgs)
Try
' Get the checkbox and return it's name
MsgBox(GetCheckBox(CInt(Me.NumericUpDown1.Value)).Name.ToString)
Catch ex As Exception
' Display the error
MsgBox(ex.Message)
End Try
End Sub
End Class
I'm quite lost in this error I'm getting. I have a Combobox that I added to my dgv, I am able to fill my combo-box with the values I want yet I keep getting an exception when I make a selection change on the dgv itself. Every time I choose a value from the combo box and then perform a selection change on the dgv the error that is thrown is : DataGridViewComboBoxCell is not valid . After this error is thrown, the value in the combo box is set to nothing.
This is my first time posting and I've done alot of research for the past two days and I can't seem to get anywhere. If you guys would like me to post my code I will do so. Thanks.
Edit: added my code:
cmbItem = New cboItem(dr.Item("strFolderName"), dr.Item("strFolderPath"), dr.Item("strEntryID"))
Dim dtmTmp As Date = oItem.ReceivedTime
dgvEmails.Rows.Insert(intEmailPosition, {False, dtmTmp.ToString("dd-MMM-yyyy hh:mm tt"), GetRecipientEmail(oItem), oItem.subject.ToString, cmbItem, oItem.conversationid.ToString, oItem.entryid.ToString, strFoundBy, oItem.body})
DirectCast(dgvEmails.Rows(intEmailPosition).Cells("cboFileTo"), DataGridViewComboBoxCell).Items.Add(cmbItem)
DirectCast(dgvEmails.Rows(intEmailPosition).Cells("cboFileTo"), DataGridViewComboBoxCell).DisplayMember = "DisplayText"
This is how I am adding the items into the combobox. Am I doing something wrong?
Edit: Added extra code
Dim cellComboBox As ComboBox = TryCast(e.Control, ComboBox)
RemoveHandler cellComboBox.SelectedIndexChanged, AddressOf Me.cellComboBox_SelectedIndexChanged
AddHandler cellComboBox.SelectedIndexChanged, AddressOf Me.cellComboBox_SelectedIndexChanged 'trapping the event handler
If cellComboBox IsNot Nothing Then
'load all values into the combox box
cellComboBox.MaxDropDownItems = 6 'drop down list can only have 5 items in there
Try
strEmail = dgvEmails.SelectedRows(0).Cells(2).Value.ToString 'cells(2) holds the email address
strConvoID = dgvEmails.SelectedRows(0).Cells(5).Value.ToString 'cells(5) holds the conversation id of the email
Catch ex As Exception
End Try
'call GetSuggestion function here
objclsSuggesstion.GetSuggestion(strConvoID, strEmail, NUMBER_SUGGESTIONS)
For intI = 0 To NUMBER_SUGGESTIONS - 1
dr = objclsSuggesstion.GetItem(intI)
If dr IsNot Nothing Then
'add dr to the combo box
cboItem = New cboItem(dr.Item("strFolderName"), dr.Item("strFolderPath"), dr.Item("strEntryID"))
'If Not cellComboBox.SelectedItem.FolderEntryID = cboItem.FolderEntryID Then 'if does not exist then add
cellComboBox.Items.Add(cboItem)
'End If
Else
Exit For
End If
Next
'cellComboBox.Items.Add(cboItem)
cboItem = Nothing 'make object nothing here
cboItem = New cboItem("", "", "", "<choose folder>...") 'create new object & add
'if <choose folder>... doesn't exist, then you add it.
Try
If Not cellComboBox.SelectedItem.DisplayText = cboItem.DisplayText Then
'cellComboBox.Items.Add(cboItem)
'DirectCast(dgvEmails.SelectedRows(0).Cells("cboFileTo"), DataGridViewComboBoxCell).Items.Add(cboItem)
'DirectCast(dgvEmails.SelectedRows(0).Cells("cboFileTo"), DataGridViewComboBoxCell).DisplayMember = "DisplayText"
cellComboBox.Items.Add(cboItem)
End If
Catch ex As Exception
End Try
I hope this helps?
I can't see all your code, but this is an example about adding a list of objects of type cmbItem to a DataGridViewComboBoxColumn
Public Class Form1
Dim myItems As New List(Of cmbItem)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
myItems.Add(New cmbItem() With {.Text = "yesterday", .DisplayText = Now.Date.AddDays(-1).ToString()})
myItems.Add(New cmbItem() With {.Text = "now", .DisplayText = Now.Date.ToString()})
myItems.Add(New cmbItem() With {.Text = "tomorrow", .DisplayText = Now.Date.AddDays(1).ToString()})
'find combobox in datagridview, passing column index
Dim ss = CType(DataGridView1.Columns(1), DataGridViewComboBoxColumn)
'add my items to combobox
For Each cmbItem As cmbItem In myItems
ss.Items.Add(cmbItem)
Next
'set combobox properties
ss.ValueMember = "Text"
ss.DisplayMember = "DisplayText"
End Sub
End Class
Public Class cmbItem
Property Text() As String
Property DisplayText() As String
End Class
Result:
If you want to add a new row, you must be sure to add a valid combobox value in the comboboxColumn. In the following code...
Private Sub AddRow()
DataGridView1.Rows.Add(New Object() {"New", myItems.First()})
DataGridView1.Rows.Add(New Object() {"New", "12/01/1984"})
End Sub
The first row is added correctly, the second one gives and exception like yours "DataGridViewComboBoxCell value is not valid."
There are a lot of ways to add new rows getting a valid combobox item, here are some examples
Private Sub AddRow2()
Dim ss = CType(DataGridView1.Columns(1), DataGridViewComboBoxColumn)
'adding from my list
DataGridView1.Rows.Add(New Object() {"New", myItems.First()})
'adding from current combobox Items
DataGridView1.Rows.Add(New Object() {"New", ss.Items.OfType(Of cmbItem).Last()})
'querying from combobox added items
Dim queryItem = (From i In ss.Items.OfType(Of cmbItem)() _
Where i.Text = "now" _
Select i).Single()
DataGridView1.Rows.Add(New Object() {"New", queryItem})
End Sub
Result
Hi I have a vb windows form application that has a ComboBox from the form1 I have some code that reads some registry and adds item results to combobox. I would like to select one of the results and run a start process. My problem is where do I put the code when item is selected then do something and how to I determine what has been selected?
My Code to query registry keys
Dim Key, Reader As RegistryKey, Y As String
Key = Registry.LocalMachine.OpenSubKey("SOFTWARE\AppStream\AppMgr\Shortcuts", False)
For Each X In Key.GetSubKeyNames
Reader = Registry.LocalMachine.OpenSubKey("SOFTWARE\AppStream\AppMgr\Shortcuts\" & X, False)
If Reader.GetValueNames().Contains("AppTitle") Then
Y = Reader.GetValue("AppTitle")
If Not ComboBox1.Items.Contains(Y) Then ComboBox1.Items.Add(Y)
End If
If i do somehting like this, it just shows a blank messagebox and I have not selected that text from combobox yet.
If ComboBox1.SelectedText Then
MessageBox.Show(ComboBox1.SelectedText())
End If
You subscribe to the SelectedIndexChanged event writing a method like this
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim comboBox As comboBox = CType(sender, comboBox)
' Caution, the event could be called also when there is nothing selected
if combBox.SelectedItem IsNot Nothing Then
Dim curValue = CType(combBox.SelectedItem, String)
'do your stuff with the selected key'
End If
End Sub
if combBox.SelectedItem IsNot Nothing Then
Dim cmbselected As String = DirectCast(DirectCast(DirectCast(DirectCast(combBox, System.Windows.Controls.ComboBox).SelectedValue, System.Object), System.Data.DataRowView).Row, System.Data.DataRow).ItemArray(0)
End If
I am using vb.net and winforms.
I have a Form with a Bound DataGridView. On the DGV I have 5 columns with ComboBox. I am using the EditingControlShowing Even to catch the ComboBox Selection. (see code bellow).
Here is the problem:
After I click on a Cell with a ComboBox and make a Selection and then update the underlying cell (cell = selected value) and then click on another Row of the DGV it goes haywire. If after I update the Cell I do and EndEdit on the corresponding row of the DataSource it seems to work find.
How can I determine whe corresponding Data Source row so that I can automate this?
Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView1.EditingControlShowing
Try
Debug.Print("entered the EditingControlShowing")
Dim ColName As String = Me.DataGridView1.Columns(Me.DataGridView1.CurrentCell.ColumnIndex).Name
If ColName = "Col1" Then 'Or ColName = "Col2" Or ColName = "Col3" Or ColName = "Col4" Or ColName = "Col5" Then
'the column you want to cast
Dim cmb As ComboBox = TryCast(e.Control, ComboBox)
RemoveHandler cmb.SelectedIndexChanged, AddressOf cmb_SelectedIndexChanged
AddHandler cmb.SelectedIndexChanged, AddressOf cmb_SelectedIndexChanged
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Sub cmb_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Try
Me.DataGridView1.Rows(Me.DataGridView1.CurrentRow.Index).Cells(Me.DataGridView1.CurrentCell.ColumnIndex).Value = CType(sender, ComboBox).SelectedItem
'
' HERE IF I PUT MyDataSet.Tables(0).Rows(?).EndEding it works - but how to konw what row?
'
UpdateAvgColumn(Me.DataGridView1.CurrentRow.Index)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
The events being fired are reentering. If you are currently processing an event, you have to be careful not to process other events. You have to put IF statements around the processing of the events to skip executing the code, if a different event is being processed.
sub dgv_selecteditemchanged()
If not processing_event
processing_event = true
...
processing_event = false
end if
end sub