How to trigger a gotfocus datagrid combobox event while grid is readonly? - vb.net

I have a datagridview and I'm trying to get the gotfocus event for my comboboxcells to still call despite the datagrid being on readonly.
This gotfocus event changes the colour of every combobox with a similar value (including itself) and I would like to it to still call while on readonly (the datagridview comboboxes can still be selected/highlighted while on readonly but it is not called(?))
Below is the basics of how I am currently handling the events (for some reason this shortened version makes multiple event calls at an exponential rate & also requires three clicks to trigger... I'm not sure why it does this but my full project works fine in this regard)
Public Class Form1
Private Sub cell_gotfocus(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
Dim CurrentCombo = TryCast(e.Control, ComboBox)
If Not CurrentCombo Is Nothing Then
RemoveHandler CurrentCombo.GotFocus, AddressOf Combo_Focus 'remove event handler so we don't accumulate multiples
AddHandler CurrentCombo.GotFocus, AddressOf Combo_Focus 'add eventhandler
End If
End Sub
Private Sub Combo_Focus()
Console.WriteLine("Got Focus")
Console.beep
End Sub
Private Sub Make_Readonly_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Make_Readonly.Click
DataGridView1.Rows(0).ReadOnly = True 'toggle readonly
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For y As Integer = 1 To 4 'add extra columns into datagrid
Dim cmb As New DataGridViewComboBoxColumn
cmb.HeaderText = "c" & DataGridView1.Columns.Count
cmb.Name = "c" & DataGridView1.Columns.Count
cmb.FlatStyle = FlatStyle.Flat
DataGridView1.Columns.Add(cmb)
Next
End Sub
End Class

Related

How to select TextBox on Label Click

In Microsoft Access, when you click on a label, the textbox associated with that label gets the focus. As far as I can tell, VB.NET does not have this same functionality. I know I can always add something in to the click event of the label, like so...
TextBox1.Focus()
But I have dozens of fields on the form, and it would make it so much easier if I did not need to add this to the click event of each label.
I guess it would be possible to make an event for all labels that forces a tab to the next control, and assuming that I have the Tab indices set up correctly, then this would work. The problem would occur when adding new fields to the form, in which case all tab indices would need re-verified.
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click, Label2.Click
'code to tab to next field...
End Sub
Is there any easier way?
First, set the controls' TabIndex orders on your form then use this code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each c As Control In Me.Controls
If TypeOf c Is Label Then AddHandler c.Click, AddressOf Label_Click
Next
End Sub
Private Sub Label_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.SelectNextControl(sender, True, True, True, True)
End Sub
End Class
Now whenever you click on a label, the following control in the order will be focused.
How about creating a dictionary where the label is the key and the control to focus is the value, then add a Click event handler to all of the label in the Dictionary. Everytime you add a label/control 'all' you need to do is add another KeyValuePair to the Dictionary
Simple Example:
Public Class Form1
Protected Friend DicLabelToControl As Dictionary(Of Label, Control)
Protected Friend Sub InitLabelDic()
DicLabelToControl = New Dictionary(Of Label, Control) From {{Label1, TextBox1}, {Label2, TextBox2}}
End Sub
Protected Friend Sub AddClickEventsToLabels()
For Each lb As Label In DicLabelToControl.Keys
AddHandler lb.Click, AddressOf HandleLabelClick
Next
End Sub
Private Sub HandleLabelClick(sender As Object, e As EventArgs)
DicLabelToControl(CType(sender, Label)).Focus()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitLabelDic()
AddClickEventsToLabels()
End Sub
End Class

Get combobox selected from another form dynamically

I have a combobox in a form1 and a datagridview in another form2.
I want to get the combobox selected with a value from the datagridview in the second form
I use the code below in form2 and it works:
Private Sub DataGridView1_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
form1.CBO_fournisseur.Text = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString
Me.Close()
End Sub
But what I want to do is that the name of the form is passed dynamically to avoid using and IFELSE clause to enumerate all the forms I have in my project that use form2
Private Sub DataGridView1_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
If formbon2.Name = "FRM_BN_RECEPTION_CUIR" Then
FRM_BN_RECEPTION_CUIR.CBO_fournisseur.Text = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString
ElseIf formbon2.Name = "frm_reception_acc_provisoire" Then
frm_reception_acc_provisoire.CBO_1.Text = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString
End If
Me.Close()
End Sub
I think I've got what you want to do. I strongly suggest you stop using the Form as a Shared resource.
Use a constructor like this in your Form2:
Private ParentFormCombo as Combobox
Public Sub New(ByVal pCmb as Combobox)
ParentFormCombo = pCmb
End Sub
Then in your doubleclick you just change the text of ParentFormCombo
ParentFormCombo.Text = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString
Then you have to stop using:
FrmList_View.Show()
Now you should always use the constructor instead (New()). So do the following instead:
Dim f As New FrmList_View(CBO_fournisseur)
'or
Dim f As New FrmList_View(CBO_1)
f.Show()

.Net WindowsForms MouseDown event not firing

As a new user to VB, I am struggling to see why this code works in one project but not in another. This code works fine if I create a new project and 2 new forms but when I place in my project, it doesn't fire at all on either left or right click.
I have tried a try/catch statement, but no errors are being reported. How do I go about troubleshooting this to find out the error. I have tried to rem out code and run after each comment but still the same. I have even tried removing all other code on the form leaving just the 2 subs but no joy. Any help would be greatly appreciated.
frmMain
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'StorageDataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.StorageDataSet1.Customers)
'TODO: This line of code loads data into the 'StorageDataSet.User' table. You can move, or remove it, as needed.
Me.UserTableAdapter.Fill(Me.StorageDataSet.User)
'Dim frmDepartmentsLive As New frmDepartment
'frmDepartmentsLive.Owner = Me
'frmDepartmentsLive.ShowDialog()
lblDate.Text = Now
Timer1.Start()
rdoCustomer.Enabled = False
rdoCustomer.Checked = True
rdoDepartment.Enabled = False
rdoDepartment.Checked = False
For Each ctrl In Me.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If (e.Button = MouseButtons.Right) Then
Dim btn = CType(sender, Button)
frmRacks.buttonName = btn.Name.Replace("btn", "")
frmRacks.Show()
ElseIf (e.Button = MouseButtons.Left) Then
MessageBox.Show("To be coded")
End If
End Sub
frmRacks
Public Class frmRacks
Public buttonName As String
Private Sub racksfrm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblRacks.Text = buttonName
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class
Since the controls are on a panel, they are members of that panel's controls array, not the form's. This -- and other things -- are apparent if you look thru the form's designer (on solution explorer, click Show All, then open formXXX.designer.vb). DOnt change anything, but it shows how controls are created and added. So...
For Each ctrl In thepanelName.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
If it is ONLY those buttons on the panel you can short cut it:
For Each btn As Button In thepanelName.Controls
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
Next

Exposing DataGridViewComboBoxEditingControl

I would like to know how to use the DataGridViewComboBoxEditingControl with vb.net
i need a routteen to run when the user select an item from the datagridviewcomboboxcolumn that i have configured. I am unsure how to attach the object to the column i create manually
I have implemented the following from examples on the internet but this only appears to trigger when the user click on the combobox within the column.
Private Sub dgvTicketDetail_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvTicketDetail.EditingControlShowing
Dim editingComboBox As ComboBox = TryCast(e.Control, ComboBox)
If editingComboBox IsNot Nothing Then
AddHandler editingComboBox.SelectedValueChanged, AddressOf EditingComboBox_DropDown
End If
End Sub
Private Sub EditingComboBox_DropDown(ByVal sender As System.Object, ByVal e As System.EventArgs)
Debug.WriteLine("A ComboBox in the DataGridView just dropped down.")
End Sub
any help would be appreciated as i cant seem to find much reference material for this
Thanks in advance
Just realised that i have never posted the answer to my question
Placed the following in the EditingControlShowing to capture request
Private Sub dgvTicketDetail_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvTicketDetail.EditingControlShowing
Try
If dgvTicketDetail.CurrentCell.ColumnIndex = 1 Then
Dim cmbox As ComboBox = TryCast(e.Control, ComboBox)
AddHandler cmbox.SelectionChangeCommitted, AddressOf Update_StockInfo
strSelectedText = cmbox.SelectedText
End If
Catch ex As Exception
End Try
End Sub
then this added items to the combobox cell
Private Sub Update_StockInfo(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim cmbClickedCell = DirectCast(sender, DataGridViewComboBoxEditingControl)
Dim cmbComboBox = DirectCast(sender, ComboBox)
If dgvTicketDetail.CurrentRow.Index = cmbClickedCell.EditingControlRowIndex And dgvTicketDetail.CurrentCell.ColumnIndex = 1 Then
Debug.WriteLine(cmbClickedCell.EditingControlRowIndex & cmbComboBox.SelectedValue)
Dim dtStock As DataTable = CropTrackMod.GetWeight(cmbComboBox.SelectedValue)
Dim dgvcc As DataGridViewComboBoxCell
dgvcc = dgvTicketDetail.Rows(cmbClickedCell.EditingControlRowIndex).Cells(2)
dgvcc.Items.Clear()
For Each row As DataRow In dtStock.Rows
dgvcc.Items.Add(row.Item("UnitName"))
Next row
If CropTrackMod.IsStockVATAble(cmbComboBox.SelectedValue) = True Then
dgvTicketDetail.Rows(cmbClickedCell.EditingControlRowIndex).Cells("VATRate").Value = CropTrackMod.dblVATRate
Else
dgvTicketDetail.Rows(cmbClickedCell.EditingControlRowIndex).Cells("VATRate").Value = "0.00"
End If
End If
End Sub
It works really well for me, unfortunately the user wanted something different in the end ha. Oh well at least i learnt something

Using handlers across multiple forms?

I have code that highlights the current textbox in focus in order to provide a visual cue to the user. My question is, if I had 10 forms with textboxes and I wanted to provide this same code to them all. Would I have to duplicate it or can I use a global method? If so, an example would be very helpful. Thanks.
The code is as follows.
Private Sub FocusChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim txt As TextBox = sender
If txt.Focused Then
txt.Tag = txt.BackColor
txt.BackColor = Color.AliceBlue
Else
txt.BackColor = txt.Tag
End If
End Sub
Private Sub CreateAccount_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each ctrl As TextBox In Me.Controls.OfType(Of TextBox)()
AddHandler ctrl.GotFocus, AddressOf FocusChanged
AddHandler ctrl.LostFocus, AddressOf FocusChanged
ctrl.Tag = ctrl.BackColor
Next
End Sub
If you want to add this behavior to all TextBox controls, you're better off deriving your own class from the TextBox class, and override the OnGotFocus and OnLostFocus methods to set the properties accordingly.
Here's how:
Public Class MyTextBox
Inherits TextBox
Protected Overrides Sub OnGotFocus(e As System.EventArgs)
MyBase.OnGotFocus(e)
Me.Tag = Me.BackColor
Me.BackColor = Color.Aqua
End Sub
Protected Overrides Sub OnLostFocus(e As System.EventArgs)
MyBase.OnLostFocus(e)
Me.BackColor = Me.Tag
End Sub
End Class
EDIT: forgot to mention that after adding that class to your project, rebuild the solution, and if it compiles without errors, then your new TextBox class show show up in the VS ToolBox. You can then simply drag & drop onto your form just as any control.
Cheers