I have a form with tab page containing several checkboxes.
I need to loop through these checkboxes to see which ones are checked. From there, I need to grab the .Tag property so that I can in turn add a property with that name from another object to t list.
I have a problem with my code though. For the line -
DirectCast(objCtrl, CheckBox).IsChecked
I'm getting the error
IsChecked' is not a member of 'System.Windows.Forms.CheckBox'
This seems odd, as I obviously need to use that method to check if the checkbox is actually checked, and the docs seem to suggest that method exists.
What am I doing wrong? Thanks.
Dim objCtrl As Control
For Each objCtrl In Me.objConfigForm.tabPageGeneral.Controls
If TypeOf objCtrl Is CheckBox AndAlso DirectCast(objCtrl, CheckBox).IsChecked Then
Dim strProp As String = DirectCast(objCtrl, CheckBox).Tag
arrGeneral.Add(objUser.strProp)
End If
Next
It seems that you are looking at the documentation for WPF CheckBox not to the docs for WinForms Checkbox
In the latter the property is named Checked
The Property you want is Checked not IsChecked
See the help for more info: http://msdn.microsoft.com/en-us/library/system.windows.forms.checkbox.checked(v=vs.110).aspx
The property is Checked, not IsChecked.
Related
I am trying to access a ComboBox on a UserForm from a sub. Therefore I'm trying to pass a Combobox object into it.
However, I don't seem to be able to create a Combobox Object in order to pass it in. They are always empty when entering the sub. This is what I've been trying:
Dim ctl As ComboBox
Set ctl = Me.cb_FcnName 'cb_FcnName is the name of the Combobox I'm trying to access
Call ColumnEntries2Combobox(ctl)
And this is my Sub:
Private Sub ColumnEntries2Combobox(ByRef Combo As ComboBox)
Combo.AddItem = Worksheets(WorksheetName).Cells(currRow, 2)
End Sub
For some reason I can't seem to find any documentation on how to create the necessary combobox object to pass into the sub...
Thanks in advance for any kind of help!
AddItem is a method, not a property. For a method we supply arguments after a space, compared to setting a property equal to something.
So change
Combo.AddItem = Worksheets(WorksheetName).Cells(currRow, 2)
to
Combo.AddItem Worksheets(WorksheetName).Cells(currRow, 2)
This is a common error, so a simple demonstration is:
object.Property = value
object.Method arg1, arg2
I'm looping through all of the controls on a certain Tab Page and the grabbing the .tag property for some further actions from checkboxes that are checked.
However, I require these controls to be looped in a certain order (I was hoping they'd be ordered by tab index), but it appears that they are not.
Is there any way to force the order that they are looped? Thanks.
Dim objCtrl As Control
For Each objCtrl In Me.objConfigForm.tabPageGeneral.Controls
If TypeOf objCtrl Is CheckBox AndAlso DirectCast(objCtrl, CheckBox).Checked Then
Dim strProp As String = DirectCast(objCtrl, CheckBox).Tag
Dim strListItem As String = CallByName(objUser, strProp, CallType.Get)
lstGeneral.Add(strListItem)
End If
Next
Use LINQ to sort the controls by TabIndex, like this:
For Each objCtrl As Control In Me.Controls.Cast(Of Control).OrderBy(Function(c) c.TabIndex)
If TypeOf objCtrl Is CheckBox AndAlso DirectCast(objCtrl, CheckBox).Checked Then
Dim strProp As String = DirectCast(objCtrl, CheckBox).Tag
Dim strListItem As String = CallByName(objUser, strProp, CallType.Get)
lstGeneral.Add(strListItem)
End If
Next
Note: The above code requires the System.Linq namespace be imported into your code file to support the Cast() and OrderBy() LINQ extension methods.
Use the .OrderBy() extension to choose an order. Also, while we're at it, you can replace the If block with Where() and OfType() extensions to reduce nesting and casting:
For Each box As CheckBox In Me.Controls.OfType(Of CheckBox)() _
.Where(Function(b) b.Checked) _
.OrderBy(Function(b) b.TabIndex)
lstGeneral.Add(CallByName(objUser, box.Tag, CallType.Get))
Next
Update: this is a bit old, but it came back into my feed today, so it's still indexed by Google somewhere. With that in mind, today I'd write the code like this instead:
Dim selectedCheckboxNames = Me.Controls.
OfType(Of CheckBox)().
Where(Function(b) b.Checked).
OrderBy(Function(b) b.TabIndex).
Select(Function(b) CallByName(objUser, b.Tag, CallType.Get))
lstGeneral.AddRange(selectedCheckboxNames)
One of the important change is introducing a variable for the result of the linq query. This can sometimes add valuable insight to code for future developers, and it always helps make the For Each loop easier to read... assuming you haven't also been able to convert to an AddRange(), as I've done here. I'm also more comfortable now taking advantage of implicit line continuations and Option Infer.
I face a problem with Ambiguous match found
What I am trying to do is described in :GetType.GetProperties
In two words I am trying to run through all the properties of a control and find if user had made any changes to control's properties , then I take only the changed properties and store the values for these properties
I followed the suggestions but I get an error for propery Padding when the control is a TabControl (the tabControl has 2 tabPages).
Ok with help from Ravindra Bagale I manage to solve it:
The problem wasn't the new modifier but my stupidity:
In MSDN is says:
Situations in which AmbiguousMatchException occurs include the following:
A type contains two indexed properties that have the same name but different numbers of parameters. To resolve the ambiguity, use an overload of the GetProperty method that specifies parameter types.
A derived type declares a property that hides an inherited property with the same name, by using the new modifier (Shadows in Visual Basic). To resolve the ambiguity, use the GetProperty(String, BindingFlags) method overload and include BindingFlags.DeclaredOnly to restrict the search to members that are not inherited.
So I used BindingFlags.DeclaredOnly and the problem solved:
Private Sub WriteProperties(ByVal cntrl As Control)
Try
Dim oType As Type = cntrl.GetType
'Create a new control the same type as cntrl to use it as the default control
Dim newCnt As New Control
newCnt = Activator.CreateInstance(oType)
For Each prop As PropertyInfo In newCnt.GetType().GetProperties(BindingFlags.DeclaredOnly)
Dim val = cntrl.GetType().GetProperty(prop.Name).GetValue(cntrl, Nothing)
Dim defVal = newCnt.GetType().GetProperty(prop.Name).GetValue(newCnt, Nothing)
If val.Equals(defVal) = False Then
'So if something is different....
End If
Next
Catch ex As Exception
MsgBox("WriteProperties : " & ex.Message)
End Try
End Sub
I have to apologize.
My previous answer was wrong.
With BindingFlags.DeclaredOnly I don't get the properties that I wanted.
So I had to correct the problem with other way.
The problem occurs because two properties have the same name.
So I searched where the same named properties are different and I found that they have: have different declaringType,MetadataToken and PropertyType.
So I change the way I get the value and problem solved:
Dim val = cntrl.GetType().GetProperty(prop.Name, prop.PropertyType).GetValue(cntrl, Nothing)
Dim defVal = newCnt.GetType().GetProperty(prop.Name,prop.PropertyType).GetValue(newCnt,Nothing)
Sorry if I misguided someone.
I am trying to programmatically check a checkbox of a ListView (using VB & .NET 4).
The ListView lvVorschlag has been created in the designer, along with three elements. I then do the following:
Dim lviOptimal As New ListViewItem("Optimal")
lviOptimal.SubItems.Add(...) 'several SubItems are added
lvVorschlag.Items.Add(lviOptimal)
lvVorschlag.Items(0).Selected = True
All the SubItems are correctly added and the line lvVorschlag.Items(0).Selected = True does not give me an error. But nothing is checked. Any idea why?
Note: I also tried with lvVorschlag.Items("Optimal").Selected = True but it gives me an error saying that this object is Nothing. Too bad, referring by name would have been easier.
You should use the Checked property to check the item(s) you'd like:
lvVorschlag.Items(0).Checked = True
Set the focus on the item
Dim lviOptimal As New ListViewItem("Optimal")
lviOptimal.SubItems.Add(...) 'several SubItems are added
lvVorschlag.Items.Add(lviOptimal)
lvVorschlag.Items(0).focus()
lvVorschlag.Items(0).Selected = True
http://msdn.microsoft.com/en-us/library/y4x56c0b%28v=vs.100%29.aspx
I recently upgraded a VB 6 project to .net. I'm having a problem with this block of code:
Dim CtrlName As System.Windows.Forms.MenuItem
For Each CtrlName In Form1.Controls
'Some code here
Next CtrlName
Now this code compiles but throws the following runtime error:
Unable to cast object of type 'System.Windows.Forms.Panel' to type 'System.Windows.Forms.MenuItem.
I have a panel control on the subject form. How do I resolve this?
Thanks.
You are iterating over all controls that are directly inside the form, not just the MenuItems. However, your variable is of type MenuItem. This is causing the problem.
For normal controls (e.g. Buttons), you’d want to use the following, easy fix; test inside the loop whether the control type is correct:
For Each control As Control In Form1.Controls
Dim btt As Button = TryCast(control, Button)
If btt IsNot Nothing Then
' Perform action
End If
Next
However, this does not work for MenuItems since these aren’t controls at all in WinForms, and they aren’t stored in the form’s Controls collection.
You need to iterate over the form’s Menu.MenuItems property instead.
The items in the Controls property of a form, which may or may not be MenuItem. Assuming that you just want to iterate over MenuItem objects you can change your code to:
For Each menuControl As MenuItem In Me.Controls.OfType(Of MenuItem)
' Some code
Next
Note that the menuControl variable is declared in the For so is only accessible within the block and is disposed automatically.
for each ctrl as control in me.controls
if typeof ctrl is menuitem then
' do stuff here
end if
next
typeof keyword allows you to test the type of control being examined in the control collection.
Found the answer after a bit of research, you need to search for the menu strip first and then loop through the items collection.
For Each ctrl As Control In Me.Controls
If TypeOf ctrl Is MenuStrip Then
Dim mnu As MenuStrip = DirectCast(ctrl, MenuStrip)
For Each x As ToolStripMenuItem In mnu.Items
Debug.Print(x.Name)
Next
End If
Next