search controls in flowlayoutpanel with "like" searchkey VB.NET - vb.net

I have a flowlayoutpanel listing the titles of an album. Assuming the flowlayoutpanel has a lot of songs and I want to find a particular one. Let's say, I would like to get the song of Ed Sheeran "Thinking Out loud." So I would type the word "Thinking" in the searchbox, and without even finishing the "Out Loud" words, I would like to filter the flowlayoutpanel showing me the control that has the title "Thinking Out Loud" and hiding all the controls without the word "Thinking." It's like an SQL search LIKE query. But I don't want to do SQL. is it possible with FLOWLAYOUTPANEL and a SEARCH TEXTBOX?

You can use the search Textbox's TextChanged event to trigger a processing of the FlowLayoutPanel's controls collection setting each control's Visible property based on the result of a VB Like Operator comparison.
Private Sub tbSearch_TextChanged(sender As Object, e As EventArgs) Handles tbSearch.TextChanged
If tbSearch.Text.Length > 0 Then
Dim compareTo As String = String.Concat("*", tbSearch.Text.ToLowerInvariant, "*")
For Each c As Control In FlowLayoutPanel1.Controls
c.Visible = (c.Text.ToLowerInvariant Like compareTo)
Next
Else
For Each c As Control In FlowLayoutPanel1.Controls
c.Visible = True
Next
End If
End Sub

Related

Show/Hide FileExplorer in Access Form

I've been trying to use a combobox to show/hide a PDF viewer that I've added into a MS Access form.
When I use the form_current event, then the form only updates when I move between the data entries. When I use the afterupdate event, the same code does nothing at all.
Does anyone have a fix? The code I have used is below, which I have tried both the AfterUpdate event for the Browser and the Form_Current event for the whole form
Private Sub PDFT900_AfterUpdate() / Private Sub Form_Current()
Dim ESNComb As String
ESNComb = Me.ESNCombo.Column(1)
If ESNComb Like "9????" Then
Me.PDFT900.Visible = True
Else
Me.PDFT900.Visible = False
End If
End Sub
In the code below, I'm hiding and showing the Adobe PDF Reader ActiveX control named, "AcroPDF0". Since the Like operator returns true on an expression match and false on a mismatch or no match, it serves as a simple boolean switch for the visible property. I've used the (*) wild card instead of (?). It works {shrug}. See demonstration images below.
Private Sub ESNCombo_AfterUpdate()
'AcroPDF0.Visible = ESNCombo.Text Like "P*"
AcroPDF0.Visible = ESNCombo.Column(0) Like "P*"
AcroPDF0.src = acroPDFOSrc
End Sub
ComboBox List Items
"File Browser" Selected in ComboBox
Toggled ComboBox back to "PDFT900"

Loop - set Textboxes to ReadOnly in all Groupboxes

I have groupboxes that contain textboxes and I want to set all of them to ReadOnly=True. Here is what I tried (doesn't work):
EDIT (I forgot about Split container):
For Each SplitCon As Control In Me.Controls
If TypeOf SplitCon Is SplitContainer Then
For Each GBox As Control In SplitCon.Controls
If TypeOf GBox Is GroupBox Then
For Each ctrl As Control In GBox.Controls
If TypeOf (ctrl) Is TextBox Then
CType(ctrl, TextBox).ReadOnly = True
End If
Next
End If
Next
End If
Next
You can simplify things a great deal. Rather than looking thru all sorts of Control collections, create an array to act as a ToDo list. Then you can get rid of all the TypeOf and CType in the loop used.
' the ToDo list
Dim GrpBoxes = New GroupBox() {Groupbox1, Groupbox2,
Groupbox3, Groupbox4}
For Each grp In GrpBoxes
For Each tb As TextBox In grp.Controls.OfType(Of TextBox)()
tb.ReadOnly = True
Next
Next
Your code no longer depends on the form layout of the moment. The only thing you have to remember is to add any new GroupBox items to your list. You can also declare the array once ever for the whole form if you prefer (or even in the For Each statement)
Rather than working with Control objects, Controls.OfType(Of T) filters the collection and returns an object variable of that type, so there is no need to cast it or skip over controls you are not interested in. You can also tack on a Where method to further refine the list to include only do those with a certain name or Tag.

How do I iterate through Components on a Windows Form?

I'm using VisualStudio 2008 on a system using .NET Compact Framework 3.5 in VB.NET and have a form that contains a couple of Components, namely Timers and Messageboxes. Part of my application is a sub that iterates through all the Controls in the form and adjusting properties like the Front or BackColor so that we can reskin the entire application on demand.
While I'm iterating through these Controls I'd also like to iterate through the Components and set some properties of the Messageboxes on the form. I've tried using a For Each to access Me.components.Components but that collection appears to be private.
For Each comp As Object in Me.components
<do something>
Next comp
Is there a way to iterate through the components?
EDIT:
I was wrong thinking that me.components.Component is private. Using Me.components.Components I get the following error:
'Components' is not a member of 'System.ComponentModel.IContainer".
You can loop throught timers with this: ....
For Each c As Object In Me.components.Components
If TypeOf c Is Timer Then
Dim tim As Timer = CType(c, System.Windows.Forms.Timer)
tim.Interval = 12345
End If
Next
Change the .Interval = 12345 with anithing you want to do to the timers.
.... And through other controls with:
For Each ctrl As Control In Me.Controls
If (ctrl.GetType() Is GetType(TextBox)) Then
Dim txt As TextBox = CType(ctrl, TextBox)
txt.BackColor = Color.LightYellow
End If
Next
Change the TextBox with the type of control
And .BackColor = Color.LightYellow with anything you want to do with the control.
Unfortunatly i don't know how to do is with MesseageBoxes :(

String to Object as Expression

I have multiple TextBox controls Monday that will hold a value. I want to be able to add up all of the Monday textboxes and store that value as monTotal. I am getting an error message that says string cannot be converted to integer.
For i As Integer = 1 To rowCount Step 1
Dim var As Object
var = "txtMonday" & i & ".Text"
monTotal = monTotal + CInt(var)
Next
The way you are attempting to obtain a reference to the text boxes is not idiomatic of VisualBasic .NET.
var = "txtMonday" & i & ".Text" ' this is not a way to obtain a reference to the text box's text
While it would be possible to accomplish something like that using reflection, you'd be much better off refactoring your code to use an array of text boxes.
Since you are probably using Windows Forms you could perhaps implement logic to find the text box control you are interested in on the form using something like this:
' assuming container is the control that contains the text boxes
For Each ctrl In container.Controls
If (ctrl.GetType() Is GetType(TextBox)) Then
If ctrl.Name.StartsWith("txtMonday") Then
Dim txt As TextBox = CType(ctrl, TextBox)
monTotal = monTotal + CInt(txt.Text)
End If
End If
Next
The example above assumes that all the txtMonday.. text boxes are placed inside a control named container. That could be the form itself, or some other panel or table.
If all the textboxes live on the form and there are none being used for other text work you could use this. You could place all the textboxes that contain values your looking for in a separate container and get them like below, but use that control collection.
Dim amount As Double = 0
For Each tb As Textbox In Me.Controls.OfType(Of Textbox)()
amount += Convert.ToDouble(tb.Text)
Next
Dim monTotal as double=0
For Each ctrl As Control In Me.Controls
If TypeOf ctrl Is TextBox AndAlso ctrl.Name.StartsWith("txtMonday") Then
monTotal = monTotal + val(ctrl.Text)
End If
Next

Looping through Controls in VB.NET

I am creating a chess program. And it is composed of sixty four picture boxes with alternating black and white background colours.
I have named them pba1, pba2, pbb1, pbb2, pbc1 and so on.
Now, I want to loop through only the black ones, for example, I want to loop through only, pba1, pbb2, pbc3 and so on.
How do I create a loop for this in VB.NET?
I know of the way to loop through similarly named controls, but I am not able to adapt that method for my problem. Can you tell me a solution?
EDIT: In pba1, pb stands for picture box, and a1 stands for the square. Just in case, you wonder why such a name.
EDIT: Check out this answer
Loop through the PictureBox's in your ControlCollection and test for BackColor. I used the Form's ControlCollection, if they are in some other type of container control use that.
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is PictureBox Then
If cntrl.BackColor = Color.Black Then
'Do Something
End If
End If
Next
Base on the additional information that you gave in your answer, the reason your example is not working is that the Controls Name is a String and you are comparing it to the PictureBox Control not the Name of the Control.
You can try using the Tag Property instead of the Name of the Control, it will be cleaner and easier to read. I just put a 1 in the PictureBox's Tag Property for Black and a 0 for White.
Private Sub OriginalColour()
For Each cntrl As Control In Me.Controls
Dim result As Integer
If TypeOf cntrl Is PictureBox Then
If Integer.TryParse(cntrl.Tag.ToString, result) Then
If result = 1 Then
cntrl.BackColor = Color.Gray
Else
cntrl.BackColor = Color.White
End If
End If
End If
Next
End Sub
Generating controls at design time via the Forms Designer only makes sense for layouts which benefit from the forms designer.
In your case, you just have 64 uniform boxes in 8 rows of 8. Don’t use the Forms Designer for this, create the controls at runtime, and don’t give them names like pba1, just put them into an appropriate data structure (such as an 8x8 array):
Private chessFields As PictureBox(8, 8)
' In Form_Load:
For i = 0 To 7
For j = 0 To 7
chessFields(i, j) = New PictureBox
' Set size, position … then, finally,
Controls.Add(chessFields(i, j))
Next
Next
That way, you can access the fields in an orderly fashion without having to go via the Form.Controls collection.
Put all the pictureboxes in an 8x8 tableLayoutPanel (also useful for scaling etc). Then
For Each pb As PictureBox In TableLayoutPanel1.Controls
Dim col As Integer = TableLayoutPanel1.GetCellPosition(pb).Column
Dim row As Integer = TableLayoutPanel1.GetCellPosition(pb).Row
If col Mod 2 = 0 Xor row Mod 2 = 0 Then
pb.BackColor = Color.Black
Else
pb.BackColor = Color.White
End If
Next
Of course you could also use an array of the squares if you have that available.
This will not affect the events (pba1.click etc).
This is fairly simple and it may be resource heavy, but it works. I have a form with 36 CheckBoxes. This takes advantage of the fact that when you copy a checkbox it just increases the number of the name. I ended up with 36 checkboxes named CheckBox1 thru Checkbox36. The Function returns a checkbox, which may be used to set or read any property.
Private Function GetCheckBox(ByVal Index As Integer) As CheckBox
Dim CKBox As checkbox
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
CKBox = cntrl
If CKBox.Name = "CheckBox" & Index Then
Exit For
End If
End If
Next
Return ckbox
End Function