Vb.net how can I set Search level as user input string - vb.net

Intro... I've got a counter in my project that counts files in specified paths. Now all this depends on the users input as concerned would go into settings and set which extensions (tbExt1.text) that should be searched for as well as path (tbpath.text). The paths are listed in lbchannel1 listbox. Now this wont matter too much to my question, but I filled it in so my example below is more understandable.
Here comes the question: The users should be able to address if its going to count TopLevelOnly (FileIO.SearchOption.SearchTopLevelOnly) or TopAndSub (FileIO.SearchOption.SearchAllSubDirectories).
So I made a combobox that they can select from either of those two options. When they select one of them, FileIO.SearchOption.SearchTopLevelOnly or FileIO.SearchOption.SearchAllSubDirectories will become the text in a textbox tbTopOrSub1.text
That brings me to the next part. Instead of for example FileIO.SearchOption.SearchAllSubDirectories in my counter, I now added tbTopOrSub1.text as I hoped this would work the same way, but now be a user depended option. Have a look:
Dim TopOrSub1 As String
TopOrSub1 = tbTopOrSub1.Text
Dim fileTotal As Integer
For Each item As String In lbChannel1.Items
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, TopOrSub1, (tbExt1.Text)).Count
Next
I thought this would work like a charm, but it doesn't seem to work. I get this error The converting from string FileIO.SearchOption.SearchTopLev to type Integer is not valid (could be bad translation since the error was in Norwegian) and I notice how it sais TopLev. I suppose its too long? I can't figure out how to get around this.

First of all put Option Strict On for your VB project. This helps alot to avoid runtime errors.
The error occurs since you try to convert a string into an enumeration (=integer).
The good thing about comboboxes is that they have a DataSource property which can hold a collection of objects of any type. Additionally they have the following Properties:
DisplayMember: Name of a (public) property of the object set
in DataSource. The value of it will be displayed in the UI as "friendly" text.
ValueMember: Name of a property of the object set in DataSource. This value will not be shown in UI but you can accesss it in your code.
See my below exmaple how to use all these:
The object which holds the display text (Name) and the Value for your File Search Option:
Class FileSearchOption
Public Property Name As String
Public Property Value As FileIO.SearchOption
End Class
Fill your combobox and set its DataSource, DisplayMember and ValueMember:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim searchOptions As New List(Of FileSearchOption)
searchOptions.Add(New FileSearchOption() With {.Name = "TopLevelOnly", .Value = FileIO.SearchOption.SearchTopLevelOnly})
searchOptions.Add(New FileSearchOption() With {.Name = "TopAndSub", .Value = FileIO.SearchOption.SearchAllSubDirectories})
ComboBox1.DataSource = searchOptions
ComboBox1.DisplayMember = "Name"
ComboBox1.ValueMember = "Value"
End Sub
Handle the action when the user has chosen a search option. Remark that it is necessary to DirectCast the SelectedValue since it is of type Object.
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim fileTotal As Integer
For Each item As String In {"G:\"}
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, DirectCast(ComboBox1.SelectedValue, FileIO.SearchOption), (tbExt1.Text)).Count
Next
End Sub

Related

VB.NET 2019 How to populate a Tag Property on a dynamic ToolstripmenuItem

I am struggling to populate a tag property on a dynamically created sub menu which I have created. I have a text file that contains a number of radio station names, BBC1, BBC2, BBC3 for example, as well as the associated stream addresses for said stations. I am able to pull in the names and apply it to the submenu. They appear fine. I can click on the submenus, and the sender() variable confirms the station names correctly. My problem is that I cannot get the Tag property for each sub menu/radio station, to store the stream address. The code gets the radio title cleans the code and inserts it into the RadioStreamsToolStripMenuItem.DropDownItems.Add(station_name) and all is fine. The code then gets the Stream address and inserts it here RadioStreamsToolStripMenuItem.Tag.ToString(). I can tell that it is wrong, but how do I go about ensuring the correct stream goes into the correct radio Tag property. Im very new to this so please be gentle, its just a little hobby.
'======================================================================
'Aquires Radio name and creates a dropdown sub menu within RadioStreams
'======================================================================
Do While (Not line Is Nothing)
If line.StartsWith("#") Then
station_name = Replace(line, "#", "")
Dim x = RadioStreamsToolStripMenuItem.DropDownItems.Add(station_name)
AddHandler x.Click, AddressOf ToolMenuItem_Click
'===================================================
'Aquires Radio Stream to add to the Tag property for each new station
'===================================================
ElseIf line.StartsWith("#") Then
Dim station_stream As String = Replace(line, "#", "")
'The following just checks if the data has gone into the correct place
For Each Myitem As ToolStripItem In RadioStreamsToolStripMenuItem.DropDownItems
If Myitem.Text = station_name Then
MsgBox("MyItems " & Myitem.ToString())
Me.Tag = station_stream
End If
Next
You could use a Dictionary to store the stations a stream addresses. Dictionary lookups are very fast.
I assumed from your code that your text file looks like this
#BBC1
#BBC1streamAddress
#BBC2
#BBC2streamAddress
#BBC3
#BBC3streamAddress
I looped through the lines of the file assigning the trimmed keys and values to the dictionary. Then looped through the dictionary filling the menu. When the user clicks a menu item we get the text of the item and search the dictionary for the correct stream address.
Private RadioDictionary As New Dictionary(Of String, String)
Private Sub OPCode()
Dim lines = File.ReadAllLines("Radio.txt")
For i = 0 To lines.Length - 1 Step 2
RadioDictionary.Add(lines(i).Trim("#"c), lines(i + 1).Trim("#"c))
Next
For Each item In RadioDictionary
Dim x = RadioStreamsToolStripMenuItem.DropDownItems.Add(item.Key)
AddHandler x.Click, AddressOf ToolMenuItem_Click
Next
End Sub
Private Sub ToolMenuItem_Click(sender As Object, e As EventArgs) Handles ToolMenuItem.Click
Dim station = DirectCast(sender, ToolStripDropDownItem).Text
Dim stream = RadioDictionary(station)
End Sub

Why does this Visual Basic code work?

What it basically does is checks if the user input is already in ComboBox1. If it is, alerts the user. If not, it adds it to the combobox
The thing I don't get is the "For Each StringIterador In ComboBox1.Items loop". How could an Item object be placed in a String variable? I know Strings are objects but... You can't just place a random object into a String variable, can you? Also the String is later used as an Item object back "ComboBox1.GetItemText(StringIterador)"
Private Sub ComboBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles ComboBox1.KeyPress
Dim StringIterador As String
If e.KeyChar = ControlChars.Cr Then
If ComboBox1.Text <> "" Then
For Each StringIterador In ComboBox1.Items
If ComboBox1.GetItemText(StringIterador).Equals(ComboBox1.Text) Then
MsgBox("ya está en la lista")
Exit Sub
Else
ComboBox1.Items.Add(ComboBox1.Text)
Exit Sub
End If
Next
End If
End If
End Sub
The documentation for the For Next statement (https://msdn.microsoft.com/en-us/library/5ebk1751.aspx) requires that "The data type of element must be such that the data type of the elements of group can be converted to it." so this code will work as long as each item can be converted to string. It's not storing the item object in a string, it's converting the item to a string and storing that.
I haven't tested this but I suspect that if you stored an object in Items that couldn't be converted to string a run-time exception would be raised. Of course since the code is adding ComboBox1.Text each time this code will only add text items and therefore won't set up a situation in which the string conversion would be invalid.
In the same way GetItemText() is documented as "If the DisplayMember property is not specified, the value returned by GetItemText is the value of the item's ToString method. Otherwise, the method returns the string value of the member specified in the DisplayMember property for the object specified in the item parameter." so, again, it's probably working because the objects added will return a string. If you added a complex object to the combobox you'd probably see the object's type displayed (which, from memory) is the fallback result of ToString().

Limiting my result set in VB

So I can fill the combobox I have going in Visual Studio just how I want with ALL results with the following:
Dim pnum As New List(Of String)
For Each polnumber As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
pnum.Add(polnumber.Policy_Number)
Next
pnum.Reverse()
Me.Policy_NumberComboBox.DataSource = pnum
Awesome. Now I want to limit the pnum by taking what was input/selected from Insured_NameTextBox on the form and only returning the Policy_Number with a matching Insured_Name. I figure this can be performed with an If statement, but everything I try (stringcompare, InsuredName_TextBox = Me.InsuredDataSet.ClaimsInsured, etc.) either doesn't limit the results OR limits the results entirely so nothing shows up. Any idea where to put the If statement and what should be compared?
UPDATE:
I think there is some confusion so I'm including the entire load sub below:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'IncidentsDataSet.Claims_Incidents' table. You can move, or remove it, as needed.
Me.Claims_IncidentsTableAdapter.Fill(Me.IncidentsDataSet.Claims_Incidents)
'TODO: This line of code loads data into the 'InsuredDataSet.Claims_Insured' table. You can move, or remove it, as needed.
Me.Claims_InsuredTableAdapter.Fill(Me.InsuredDataSet.Claims_Insured)
'textbox autocomplete mode
Dim Iname As New AutoCompleteStringCollection()
For Each insname As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
Iname.Add(insname.Insured_Name)
Next
Me.Insured_NameTextBox.AutoCompleteCustomSource = Iname
'combobox autocomplete code (now sorting by last included!)
Dim pnum As New List(Of String)
For Each polnumber As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
pnum.Add(polnumber.Policy_Number)
Next
pnum.Reverse()
Me.Policy_NumberComboBox.DataSource = pnum
End Sub
Try something like this:
Me.Policy_NumberComboBox.DataSource = InsuredDataSet.Claims_Insured.Where(Function(r) r.Insured_Name = Insured_NameTextBox.Text).Select(Function(r) r.Policy_Number).Reverse()
We're getting closer. Based on the update to your question, you're running this code when the form loads. However, at the point where the form loads, your textbox will always be empty. What do you do when the value in the textbox changes, to re-filter your data?
This is C#
Me.InsuredDataSet.Claims_Insured.Where(x => x.Insured_Name == Insured_NameTextBox.Text);

How to access to the properties of an UserControl from code side?

make my own UserControl and I can aggregate new TabPages to a TabControl and then, inside of then TabPage, I add my own UserControl using the following code.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim TabX As New Windows.Forms.TabPage("Tab " & TabCount.ToString) '(ConfiguracionTabPage)
Dim MyControl As New ClientesEmpresa
MyControl.Name = "Control" & TabCount.ToString
If ClientesTabControl.TabPages.Count = 10 Then
ClientesTabControl.TabPages.RemoveAt(9)
End If
TabX.Controls.Add(MyControl)
TabX.Name = "Tab" & TabCount.ToString
TabX.Text = "Tab" & TabCount.ToString
MyControl.TitularLbl.Text = "Coca Cola"
Me.ClientesTabControl.TabPages.Insert(0, TabX)
Me.ClientesTabControl.SelectedIndex = 0
TabCount += 1
End Sub
My user control have several Labels, TextBox and TabPages(inside of a TabControl).
Now I want to change some properties dynamically from the source code, but I don't know how to access them.
The most similar theme that I found is this How to Acces of an User control in c#, but, as the title says, is in C#, how I can do it in VB.NET?
Sorry, I just notice that the Enter key post the comment. :(
Thanks for your feedback, I understand what are you saying but I missing something in the middle.
When I create the control in running time in the above code I can access easily to the properties of the created object, in this case my UserControl, but I don't understand how to reach the properties of a particular instance of that control from outside of Button_Click; ie. another button_click event(second button)
I was thinking to use something like
Dim ControlList As Windows.Forms.Control() = Me.ClientesTabControl.TabPages(0).Controls.Find("ModeloLbl", True)
or
ClientesTabControl.TabPages(0).Controls.OfType(Of AlarmasVehiculo)()
But I'm stuck here.
------------------------------------- 3th post ---------------
Thanks Steve, I was resolved using "Control.Find" and a For Each but your solution is easier.
There's any way to get the name of the selected tab or I must to create an Array when I create the New TabPage?, the idea is to update the text of the controls inside of the selected tab only when is selected by the user or every 5 seconds but just the in selected one.
Thanks.
To borrow M4N's answer from the C# question, and translate it to VB:
Cleanest way is to expose the desired properties as properties of your usercontrol, e.g:
Public Class MyUserControl
' expose the Text of the richtext control (read-only)
Public ReadOnly Property TextOfRichTextBox As String
Get
Return richTextBox.Text
End Get
End Property
' expose the Checked Property of a checkbox (read/write)
Public Property CheckBoxProperty As Boolean
Get
Return checkBox.Checked
End Get
Set (value As Boolean)
checkBox.Checked = value
End Set
End Property
'...
End Class
In this way you can control which properties you want to expose and whether they should be read/write or read-only. (of course you should use better names for the properties, depending on their meaning).
Another advantage of this approach is that it hides the internal implementation of your user control. Should you ever want to exchange your richtext control with a different one, you won't break the callers/users of your control.
To answer your second question, if you need to access your dynamically created controls, you can do so easily using their names, for instance:
Dim c As ClientesEmpresa= CType(Me.ClientesTabControl.TabPages("Tab1").Controls("Control1"), ClientesEmpresa)
c.CheckBoxProperty = True

How to change the data source of a ComboBox?

I have two comboboxes. The data sorce of combobox1 is a list of string that is fixed. Combobox2's data sorce will be a list of string that depends on the selection of combobox1. This is very similar to a common case as follows: first enter your contry, then depending on your enter, the second combobox will show you the list of universities in the country.
'Change selection of first combobox
Private Sub cbxClient_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbxClient.SelectedIndexChanged
Try
If cbxClient.SelectedIndex <> -1 Then
GetAccount()
End If
Catch
Throw
End Try
End Sub
'Based on selection of first combobox, update the data sorce of second combobox
Private Sub GetAccount()
Try
m_listAccount.Clear()
Dim strClient As String = cbxClient.SelectedItem.ToString
For i As Integer = 0 To m_listDS.Count - 1
If m_listDS(i).Client.Tostring = strClient Then
m_ds = m_listDS(i)
Exit For
End If
Next
If Not m_ds Is Nothing Then
For Each row As DataRow In m_ds.Tables("Account").Rows
m_listAccount.Add(row("account").ToString)
Next
End If
cbxAccount.DataSource = m_listAccount
Catch ex As Exception
End Try
End Sub
My problem is that though m_listAccount updates (has the correct information), the choices shown in cbxAccount are not updated according to m_listAccount (has the wrong information). I do not understand why this happens.
Note: Assume that old string in m_listAccount is {"old1"} (the list only has 1 string) and after updating, the string in m_listAccount is {"new"}. Through break points, I get the following:
cbxAccount.DataSorce={"new"}
cbxAccount.SelectedItem={"old1"}
In the form, cbxAccount shows "old1" string.
Try this,
cbxAccount.DataSource = Nothing
cbxAccount.DataSource = m_listAccount
If you are just updating the same list object, the datasource might not automatically update, but should if the pointer changes to the datasource.
Or you could try,
m_listAccount.AcceptChanges()
If m_listAccount is a DataTable
Doesn't look like you're actually calling the databind method, i.e.
cbxAccount.DataBind()
Try putting that just after you set the data source.