Issue detecting checkbox state in DataGridView - vb.net

I have a DataGridView control in a .Net application that contains a checkbox column. I would like for the user to be able to edit the checkboxes. The issue that I am running into is that I cannot detect the state of the checkbox after the user checks it.
If the checkbox was originally checked, then it will return checked as soon as the DataGridViewCheckBoxCell gets focus. But, if I click on the checkbox again and unchecks it, then it still returns checked. From that point on, it will always return checked regardless of the actual state of the checkbox until it looses focus and gains it again.
Likewise, if the checkbox was originally unchecked, then when it gets focus it will return unchecked in the click event regardless of what the state of the checkbox actually is.
Here is my code.
Private Sub grdTemplates_CellContentClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles grdTemplates.CellContentClick
Dim strValue As String = ""
Try
If Me.grdTemplates.Columns(e.ColumnIndex).Name = "colCurrentTemplate" Then
'The user clicked on the checkbox column
strValue = Me.grdTemplates.Item(e.ColumnIndex, e.RowIndex).Value
'THIS VALUE NEVER CHANGES WHILE THE DataGridViewCheckBoxCell HAS FOCUS
Me.lblTemplates.Text = strValue
End If
Catch ex As Exception
HandleError(ex.ToString)
End Try
End Sub
Thanks in advance,
Mike

Include this in your code:
Sub dataGridView1_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As EventArgs) Handles dataGridView1.CurrentCellDirtyStateChanged
If dataGridView1.IsCurrentCellDirty Then
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
Source: http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx

Related

Unchecking a Previously Selected Checkbox when another checkbox is checked

My form has 3 checkboxes available to the User. When the User mistakenly checks one Checkbox and realizes the mistake then checks the correct Checkbox, I need the incorrect checked Checkbox to Uncheck automatically.
I have diligently searched the web but have been unable to find any sites that offer answers for VB 2010. Mostly they provide solutions for HTML, Excel, Java, etc.
Private Sub BeginnerForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
StartupForm.Close()
If Me.CheckBox1.Checked Then
Me.CheckBox2.Checked = False
Me.CheckBox3.Checked = False
ElseIf Me.CheckBox2.Checked Then
Me.CheckBox1.Checked = False
Me.CheckBox3.Checked = False
ElseIf Me.CheckBox3.Checked Then
Me.CheckBox1.Checked = False
Me.CheckBox2.Checked = False
End If
End Sub
The results of this code is that it does not uncheck the Checkbox(es). I get no error code, it just does not UNCHECK the Checkbox(es). I have also tried other code entries such as Me.Checkbox2.CheckState.Checked = CheckState.Unchecked to no avail. Trusting you can steer me in the right direction to UNCHECK a Checkbox when another Checkbox is CHECKED.
First of all, as mentioned by daShier, you place the code in the wrong event handler. Since you want to uncheck the other checkboxes when one is being checked, you must put the code in the either Click or CheckChanged event handler of all your checkboxes that take part in this selection logic. I would suggest to put in the CheckChanged event since it will be triggered even when your checkbox check state is changed through code in addition to through mouse or keyboard actions.
' declare variable to keep track of the previous selected checkbox
Dim prevSelectedCheckBox As CheckBox
' all checkboxes to be controlled are handled by this event handler
Private Sub CheckBoxes_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged, CheckBox2.CheckedChanged, CheckBox3.CheckedChanged
' first, identify which checkbox is triggering this event
Dim this As CheckBox = DirectCast(sender, CheckBox)
' if this event is triggered when this checkbox is being checked
If this.Checked Then
' if there is a checkbox previously selected/checked
If prevSelectedCheckBox IsNot Nothing Then
prevSelectedCheckBox.Checked = False ' uncheck it
End If
' now this checkbox is currently the checked one, save it to the variable
prevSelectedCheckBox = this
' if event is triggered by unchecking this checkbox, and this checkbox is the previously checked checkbox
ElseIf this.Equals(prevSelectedCheckBox) Then
' clear the variable since now, there is no checkbox is being checked
prevSelectedCheckBox = Nothing
End If
End Sub
However, if user can only select one option among the options represented by the checkboxes, you better use radio button instead.
It appears you are processing the code in the wrong handler. You are changing things when closing the form. Try moving the code to the CheckBoxx.CheckedChanged handlers:
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
CheckBox2.Checked = False
CheckBox3.Checked = False
End Sub
UPDATE: I realize that your original code that I copied and pasted would cause a loop since the changing of the checkbox states would trigger the other routines. It's not necessary since you only need clear the other boxes if the box your user is clicking is checked.
You will need to add similar code to CheckBox2.CheckedChanged and CheckBox3.CheckedChanged as well.
Also, I should point out that you are trying to make checkboxes act as radio buttons. Why not replace the checkbox controls with radio buttons instead so that VB handles the one-only behavior for you?

Triggering an event in VB based on a change in a control in a group box

I have a group box with multiple Checkboxes(food item) and each one has a corresponding NumericUpDown control(quantity). For context, it is for a project based on a restaurant menu. I want to hide a button called btnSave whenever either a checkbox is unchecked or the quantity (NumericUpDown) is changed. I currently have btnSave.Hide under the CheckBox1_CheckedChanged and NumericUpDown1_CheckedChanged SubProcedures but I want to know if there's a way to do this when anything within this group box is changed instead of putting the code under each SubProcedure. Thanks
I think you meant .ValueChanged for the NumericUpDown control. (There is no .CheckedChanged) Although this doesn't matter much in this case, this is a good pattern for future reference. Instead of calling an event call a Sub from your events.
When you have several controls responding to a single Event handler, you can find out which control triggered the event by checking the sender parameter. Since, as you can see, sender is an Object you will have to cast it to the appropriate type to get the properties of a CheckBox.
Private Sub HideSaveButton()
btnSave.Hide
End Sub
Private Sub CheckBoxInGroupBox_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged, CheckBox2.CheckedChanged
HideSaveButton()
Dim WhichCheckBox As CheckBox = DirectCast(sender, CheckBox)
Select Case WhichCheckBox.Name
Case "CheckBox1"
MessageBox.Show("CheckBox1 has changed")
Case "CheckBox2"
MessageBox.Show("CheckBox2 has changed")
End Select
End Sub
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
HideSaveButton()
End Sub

vb.net ComboBox Text Changing When Left

I'm having an issue with my ComboBoxes whereby if I type into it to get a value & then tab out the Text changes to the first item in the list with the first letter typed.
I have:
AutoCompleteMode set to SuggestAppend
AutoCompleteSource set to ListItems
DropDownStyle set to DropDownList
I add the items for the ComboBox in the Load event of the Form the ComboBox is on.
e.g. the below is code from a Load event where I populate a ComboBox that I have set up as below.
`Me.ComboBox1.Text = ""
Me.ComboBox1.Items.Add("a")
Me.ComboBox1.Items.Add("aaa")
Me.ComboBox1.Items.Add("combo")
Me.ComboBox1.Items.Add("combobox")
Me.ComboBox1.Items.Add("combobox test")
Me.ComboBox1.Items.Add("common")
Me.ComboBox1.Items.Add("common dialog")`
After running the code, if I select the ComboBox1 & type in common - common is selected in ComboBox1 but if I leave ComboBox1 the Text reverts to combo.
It gets a bit stranger as if I user the below code in the ComboBox1_Leave event procedure it throws common:
MsgBox(ComboBox1.Text)
I've also tried assigning the value of Text to a string in the ComboBox1_KeyUp event procedure & then assign that to ComboBox1.Text in the ComboBox1_Leave event procedure but that doesn't do anything.
If I put a the above MsgBox code before assigning the strings value to ComboBox1.Text then the Text value does revert to Common but this is isn't a practical solution.
I've also noticed that if I hit Enter before hitting tab it retains the correct value but again I'm don't think this is a particularly practical solution.
Does anyone have any idea what's going on here & how I can fix it?
It is absolutely necessary to have the DropDownStyle set to DropDownList?
Because if you set DropDownStyle to DropDown the selected value will be retained when you press tab or lose the focus.
If it's absolutely necessary to have it that way, you could try this.
Public Class Form2
Dim selectedTextForCombo As String = ""
Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.ComboBox1.Text = ""
Me.ComboBox1.Items.Add("a")
Me.ComboBox1.Items.Add("aaa")
Me.ComboBox1.Items.Add("combo")
Me.ComboBox1.Items.Add("combobox")
Me.ComboBox1.Items.Add("combobox test")
Me.ComboBox1.Items.Add("common")
Me.ComboBox1.Items.Add("common dialog")
End Sub
Private Sub ComboBox1_LostFocus(sender As Object, e As System.EventArgs) Handles ComboBox1.LostFocus
ComboBox1.SelectedItem = selectedTextForCombo
'This is just for a visualization of your issue
'Label1.Text = selectedTextForCombo
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
selectedTextForCombo = ComboBox1.Text
'This is just for a visualization of your issue
'Label1.Text = selectedTextForCombo
End Sub
End Class
Warning:
This example works with the tab action.
If the users writes something that doesn't exist like "commun" the
selected value will end up being the visually selected value, in this
case: "common"

How can I find the sender of ContextMenuStrip?

Situation:
I have a context menu in a VB.NET form with fires an event handler on ItemClicked. The auto-generated subroutine receives sender and e as parameters. As I don't reinvent the wheel multiple times, I linked this context menu to three text boxes. Let's name them Textbox1, Textbox2 and Textbox3.
Problem: How can I figure out in which textbox the menu was opened?
Okay, what did I already try?
sender contains the menu itself,
e.ClickedItem just returns the single menu item that was selected.
sender.Parent is always nothing
sender.OwnerItem is also always Nothing`
Me.Textbox1.Focused is always False, even if its the "parent" control of the menu.
Okay, I found a solution that works fine, and here's the code for all VB.NET coders that have the same problem.
The context menu is linked in TextBox1, so we need to add another event handler that saves the sending control into the menu:
Private Sub TextBox1_MouseUp(sender As Windows.Forms.Control, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp
If e.Button = Windows.Forms.MouseButtons.Right Then
ContextMenu.Tag = sender
End If
End Sub
And this is the code of the event handler when clicking a menu item:
Private Sub ContextMenu_ItemClicked(sender As System.Object, e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles ContextMenu.ItemClicked
ContextMenu.Close()
If ContextMenu.Tag Is Nothing Then
Debug.Print("debug info: forgot to set sender? well ... KABOOM!")
Exit Sub
End If
Dim oParent As Windows.Forms.Control
Try
oParent = ContextMenu.Tag
Catch ex As Exception
Debug.Print("debug info: tag contains data other than sender control. well ... KABOOM!")
Exit Sub
End Try
' Do fancy stuff here.
' Release sender
ContextMenu.Tag = Nothing
End Sub
The ContextMenuStrip has a SourceControl property which contains a reference to the control which opened the menu. The event fires from one of the ToolStripMenuItems in the ContextMenuStrip, so you have to get the "parent" first:
' cast sender to menuitem
Dim mi = CType(sender, ToolStripMenuItem)
' cast mi.Owner to CMS
Dim cms = CType(mi.Owner, ContextMenuStrip)
' the control which opened the menu:
Console.WriteLine(cms.SourceControl.Name)
Under certain conditions the SourceControl can get lost but you can track it yourself with a variable and the parent ContextMenuStrip Opening event:
' tracking var:
Private MenuSourceControl As Control
Private Sub cms_Opening(sender As Object, e As CancelEventArgs) Handles cms.Opening
' set reference in case/before it is lost
MenuSourceControl = CType(sender, ContextMenuStrip).SourceControl
End Sub
Private Sub CutToolStripMenuItem_Click(sender...
If MenuSourceControl IsNot Nothing Then
' do your stuff
' optionally clear the tracking var
MenuSourceControl = Nothing
End If
End Sub
It should be also easier to get the SourceControl when dealing with sub items
You can also capture the related control in the MouseDown event of the related Control in cases where the same menu is used with different controls:
Private Sub lv2_MouseDown(sender As Object,
e As MouseEventArgs) Handles lv2.MouseDown,
myLV.MouseDown, lv1.MouseDown ...
If e.Button = Windows.Forms.MouseButtons.Right Then
MenuSourceControl = DirectCast(sender, Control)
End If
End Sub

NumericUpDown.value is not saved in the User Settings

I have a NumericUpDown Control on a form. In the Application Settings / Properties Binding, for the value parameter, i can't select my USER setting called : Heures (Integer / User).
I tried to save the value by this way :
Private Sub NumericUpDownHeures_Leave(sender As System.Object, e As System.EventArgs) Handles NumericUpDownHeures.Leave
My.Settings.Heures = NumericUpDownHeures.Value
My.Settings.Save()
End Sub
But it's not saved.
No problem for other settings (String / User). But i don't understand why the settings (Integer / User) are not saved.
Please help, Thanks.
As you are putting "NumericUpDown1.Value" you have to set the value at My.Settings.Heures to decimal.
In Form1_Load add:
NumericUpDownHeures.Value = My.Settings.Heures
and add to the event listener for your button or other widget:
My.Settings.Heures = NumericUpDownHeures.Value
I would guess the issue is that the Leave event is not being fired as you expect it to be, especially if the user just clicks the up/down arrows. I suspect that it is only fired when the user actually clicks into the value area, then leaves. You could verify this by debugging to see if your code is ever hit or by showing a simple msgbox from that event.
I think that you will have better luck if you hook the LostFocus or ValueChanged event.
I want to add to this as well for anyone looking at this in the future.
Save your settings as shown already by putting
My.Settings.Heures = NumericUpDownHeures.Value into your ValueChanged event, and then doing reverse in the form load event.
The problem is, this value changed event fires before the form load when you first initialize, so it will keep defaulting to whatever value you have set in the designer because you're overwriting the setting value with the designer value.
To get around this, you need a private/public boolean at the top of your code that is only set to true once your form has loaded (set to true at the bottom of your form_load event), then you can add the condition to the ValueChanged event checking if the form is loaded yet or not. If it is, then change the setting value, if not, then don't.
An example:
Private IsFormLoaded As Boolean = False
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
NumericUpDown1.Value = My.Settings.SavedNumValue
IsFormLoaded = True
End Sub
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
If IsFormLoaded = False Then Exit Sub
My.Settings.SavedNumValue = NumericUpDown1.Value
End Sub
OR
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
If IsFormLoaded Then
My.Settings.SavedNumValue = NumericUpDown1.Value
End If
End Sub