Search listview for multiple results - vb.net

I have accomplished to search my list view item, but unfortunately it shows the first result only and nothing beyond that
This is my code
Private Sub ULButton1_Click(sender As Object, e As EventArgs) Handles ULButton1.Click
If ComboBox2.Text = "" Then
MessageBox.Show("Please select an office")
Else
Dim itm As ListViewItem
itm = Me.ListView2.FindItemWithText(TextBox1.Text)
If Not itm Is Nothing Then
ListView2.SelectedItems.Clear()
ListView3.Clear()
ListView3.View = View.Details
ListView3.FullRowSelect = True
ListView3.GridLines = True
ListView3.Sorting = SortOrder.Ascending
ListView3.Columns.Add("Username", CInt(ListView1.Width / 2))
ListView3.Columns.Add("Name", CInt(ListView1.Width / 2))
Me.ListView2.Items.Item(itm.Index).Selected = True
For Each itm2 As ListViewItem In Me.ListView2.SelectedItems
Me.ListView3.Items.Add(ListView2.Items(itm2.Index).Clone())
Next
Else
MessageBox.Show("Not Found", "")
End If
itm = Nothing
End If
End Sub
When I enter a string in the textbox, this code will show results of listview item in another listview, is there a way I can modify this to show multiple related items to the string I enter in the textbox?
Thank you

FindItemWithText finds only the first matching item.
You would need to use another form or that function that takes the starting index and keep finding next item in a loop.
Also, this fragment looks strange:
Me.ListView2.Items.Item(itm.Index).Selected = True
For Each itm2 As ListViewItem In Me.ListView2.SelectedItems
Me.ListView3.Items.Add(ListView2.Items(itm2.Index).Clone())
Next
You iterate over selected items, but you just selected one! An you already know it's index...

Related

How to find a toolstripitem based on its name being a variable and then change the checked value of it

I have a ContextMenuStrip called: DGVContextStrip its displayed when the user right clicks on my datagridview.
That MenuStrip contains an item called AddUpgradeTagToolStripMenuItem
which contains sub items(dropdownitems), these sub items are all named with a number in their name.
eg: Add1ToolStripMenuItem, Add2ToolStripMenuItem, Add3ToolStripMenuItem.... and so on until Add25ToolStripMenuItem.
When a user right clicks, on the Datagridview, I want to check if a cell contains the number "1" then if it does make Add1ToolStripItem.checked = true
I figured I would loop through the numbers 1 to 25, and in each loop check if the cell contains 1 and if true, change the checked value of the menu item. something like...
For i = 1 to 25
If DataGridView1.SelectedRows(0).Cells("Text_Field").Value.ToString.Contains(i) then
CType("Add" & i & "ToolStripMenuItem", ToolStripMenuItem).Checked = True
Next
but this doesn't work, iv seen examples online that use the control.find method but i couldn't get that to work for my use.
for example
Dim ControlName As String = "Add" & i & "ToolStripMenuItem"
CType(Me.Controls.Find(ControlName, True), ToolStripMenuItem).Checked = True
any ideas how I get this to work? I realise I could have used 25 if then else statements but I kind of wanted to keep the code far neater.
The ToolStripItem is not a control to search for one in a Control.ControlCollection. You need to search a ToolStripItemCollection where it belongs.
Just like the Control.ControlCollection.Find method, the ToolStripItemCollection.Find method can perform a deep search for an item.
Examples for your case:
Dim itemName As String = $"Add{i}ToolStripMenuItem"
Dim tsmi = yourContextMenuStrip.Items.
Find(itemName, True).
OfType(Of ToolStripMenuItem).
FirstOrDefault()
If tsmi IsNot Nothing Then
tsmi.Checked = True
End If
Alternatively, if you already know that the target item is one of the AddUpgradeTagToolStripMenuItem drop down items, then you can do:
Dim itemName As String = $"Add{i}ToolStripMenuItem"
Dim tsmi = DirectCast(AddUpgradeTagToolStripMenuItem, ToolStripMenuItem).
DropDownItems.OfType(Of ToolStripMenuItem).
FirstOrDefault(Function(x) x.Name.Equals(itemName, StringComparison.OrdinalIgnoreCase))
If tsmi IsNot Nothing Then
tsmi.Checked = True
End If
In case you need to check only one item from the collection:
Dim itemName As String = $"Add{i}ToolStripMenuItem"
For Each tsmi In DirectCast(AddUpgradeTagToolStripMenuItem, ToolStripMenuItem).
DropDownItems.OfType(Of ToolStripMenuItem)
If tsmi.Name.Equals(itemName, StringComparison.OrdinalIgnoreCase) Then
tsmi.Checked = True
Else
tsmi.Checked = False
End If
Next

How to use function to prevent duplicated record for datagridview

I use function to prevent the same record goes into my datagridview but it doesnt work , when i separate the code out then its worked
i tried to seperate the for loop part out then the code work , but i wan to use function to do it so the code look more neater
Private Sub PicFavNote10_Click(sender As Object, e As EventArgs) Handles picFavNote10.Click
If validationDataGrid(lblNameNote10.Text) <> True Then
'if item didn added to the favorite data table yet
'add to favorite table
addTofavorite(lblUserLogin.Text, lblNameNote10.Text, lblDecpNote10.Text, txtPicNote10.Text, "SmartPhone", lblPriceNote10.Text)
End If
lblPriceNote10.Text = FormatCurrency(lblPriceNote10.Text)
End Sub
Private Function validationDataGrid(ByRef data As String) As Boolean
'validation on data grid view
For Each itm As DataGridViewRow In DGTFavTable.Rows 'loop though every item in datagrid
If itm.Cells(0).Value = data Then 'check wherter the text already exist
MsgBox(data & " Already added to your favorite cart")
Return True
Else
Return False
End If
Next
End Function
I expected the MsgBox(data & " Already added to your favorite cart") will excecute but instead the validationDataGrid function return false value even the item is already added to favorite datagridview
Before you loop all rows you need to call this sub as is an efficient workaround to validate new data on DataGridView:
Private Sub ForceGridValidation()
'Get the current cell
Dim currentCell As DataGridViewCell = DGTFavTable.CurrentCell
If currentCell IsNot Nothing Then
Dim colIndex As Integer = currentCell.ColumnIndex
If colIndex < DGTFavTable.Columns.Count - 1 Then
DGTFavTable.CurrentCell = DGTFavTable.Item(colIndex + 1, currentCell.RowIndex)
ElseIf colIndex > 1 Then
DGTFavTable.CurrentCell = DGTFavTable.Item(colIndex - 1, currentCell.RowIndex)
End If
'Set the original cell
DGTFavTable.CurrentCell = currentCell
End If
End Sub

Issue Preventing Duplicates from Being Added to a Listbox When Listbox Contains Items Loaded from a Save File

I am experiencing issues preventing duplicates from being added to a listbox.
My Windows Form has 2 listboxes
The form is designed so that when the user clicks a button, the items they have checked in first box are added to the second box
The code below that I have added to the "add" button is intended to prevent the checked item in box 1 from being added to box 2 IF an identical item already exists in box 2.
The problem with my code is that it is not stopping a duplicate from being added to box 2 if box 2 contains items that were loaded from a save file.
Any thoughts on how to fix this issue?
Public Sub additems_Click(sender As Object, e As EventArgs) Handles additems.Click
Dim itemChecked As Object
Dim alreadyonkey As Boolean
Dim duplicates As Integer = 0
If box1.CheckedItems.Count > 0 Then
For Each itemChecked In box1.CheckedItems
alreadyadded = False
'Check if item selected has already been added to box2
If box2.Items.Contains(itemChecked) = True Then
alreadyadded = True
duplicates = duplicates + 1
Else
alreadyadded = False
End If
'Add item if all criteria met
If box2.Items IsNot "" And alreadyadded = False Then
box2.Items.Add(itemChecked)
End If
Next
If duplicates > 0 Then
MsgBox("One or more of the items you are trying to add have already been added.", MsgBoxStyle.Critical, "Item has already been added")
alreadyadded = False
End If
End If
End Sub
I figured out the issue with my code... The issue was primarily due to the fact that a nested For Each loop needed to be used to compare each item in box1 to each item in box2 one at a time and the items needed to be sent to string variables and them compared using "String.Equals".
Public Sub additems_Click(sender As Object, e As EventArgs) Handles additems.Click
Dim itemChecked As Object
Dim alreadyadded As Boolean
Dim duplicates As Integer = 0
If box1.CheckedItems.Count > 0
For Each itemChecked In box1.CheckedItems
Dim itemtoadd As String = itemChecked.ToString
'Check if item selected has already been added to box2
For Each item In box2.Items
Dim box2item As String = item.ToString
If String.Equals(Trim(itemtoadd), Trim(box2item)) = True Then
alreadyadded = True
duplicates = duplicates + 1
Else
End If
Next
'Add item if all criteria met
If itemChecked IsNot "" And alreadyadded = False Then
box2.Items.Add(itemChecked)
End If
Next
If duplicates > 0 Then
MsgBox("One or more of the items you are trying to add have already been added.", MsgBoxStyle.Critical, "Item hase already been added")
alreadyadded = False
duplicates = 0
End If
End If

Mutually Exclusive Comboboxes?

So, I've got 4 Comboboxes. They all share the same list of options, lets say Apple, Banana, Carrot, Dill.
However, once the user selects one, that selection should not be available in the other comboboxes. E.g. if they pick Apple in Combobox1, then the only selections available in Combobox2, 3, and 4 should be Banana, Carrot, and Dill.
Is there a good way to do this? I originally thought to link the boxes datasource to a list containing the options, but they need separate datasources for separate choices.
Radio and checkboxes aren't really an option in the actual program, as the list of options is much larger than 4. A Combobox seems to be the best way to represent the user's available choices here.
Here's a fairly simple way to do what you are asking. This code assumes that the datasource uses an integer value to keep track of the items. If you are using the string value itself {Apple, Banana, etc.} as the id, the code will need to be amended slightly. If you need further help let me know but hopefully this gets you on the right track.
You can test this by creating a new blank form (Form1) and drop 4 combo boxes onto it (ComboBox1, ComboBox2, ComboBox3, ComboBox4). Copy/paste this code over top of the form code and run to see how it works:
Public Class Form1
Dim oComboBoxArray(3) As ComboBox
Dim bPreventSelectedChange As Boolean = False
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Set up an array with the combo box references to reduce code size by using loops later
oComboBoxArray(0) = Me.ComboBox1
oComboBoxArray(1) = Me.ComboBox2
oComboBoxArray(2) = Me.ComboBox3
oComboBoxArray(3) = Me.ComboBox4
' Populate all four combo boxes with the same datasource to start
For Each oCbo In oComboBoxArray
PopulateDataSource(oCbo)
Next
End Sub
Private Sub PopulateDataSource(oCombo As ComboBox, Optional nIdToSelect As Integer = 0)
bPreventSelectedChange = True ' Prevent code in ComboBox_SelectedIndexChanged from executing while we change the datasource
' Using manually populated datatable as datasource because it's quick and easy to use
Dim dt As New DataTable
Dim dr As DataRow
dt.Columns.Add("ID", GetType(Int32))
dt.Columns.Add("Name", GetType(String))
' Need to have some kind of "Please select an item:" in the list or else we will be unable to clear an already selected combo box
dr = dt.NewRow
dr("ID") = 0
dr("Name") = "Select..."
dt.Rows.Add(dr)
' If you are populating from a database or other dynamic source you will only have one of these 'if' statements within a loop
If CheckSkipItem(oCombo, 1) = False Then
dr = dt.NewRow
dr("ID") = 1
dr("Name") = "Apple"
dt.Rows.Add(dr)
End If
If CheckSkipItem(oCombo, 2) = False Then
dr = dt.NewRow
dr("ID") = 2
dr("Name") = "Banana"
dt.Rows.Add(dr)
End If
If CheckSkipItem(oCombo, 3) = False Then
dr = dt.NewRow
dr("ID") = 3
dr("Name") = "Carrot"
dt.Rows.Add(dr)
End If
If CheckSkipItem(oCombo, 4) = False Then
dr = dt.NewRow
dr("ID") = 4
dr("Name") = "Dill"
dt.Rows.Add(dr)
End If
oCombo.DataSource = dt
oCombo.DisplayMember = "Name"
oCombo.ValueMember = "ID"
oCombo.SelectedValue = nIdToSelect ' Set value to either a) the "Select..." item or b) the item that was selected previously depending on the situation
bPreventSelectedChange = False ' Allow code in ComboBox_SelectedIndexChanged to be executed by user again
End Sub
Private Function CheckSkipItem(oCombo As ComboBox, nID As Integer) As Boolean
Dim bSkip As Boolean = False
' Loop through all combo boxes and see if this id has already been chosen in another combo box
For Each oCbo In oComboBoxArray
If oCbo IsNot oCombo AndAlso oCbo.SelectedValue = nID Then
' It has been chosen already so it is not valid for the current combo box that we are checking
bSkip = True
Exit For
End If
Next
Return bSkip
End Function
Private Sub ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged, ComboBox2.SelectedIndexChanged, ComboBox3.SelectedIndexChanged, ComboBox4.SelectedIndexChanged
' Jump out of this event if the bPreventSelectedChange boolean is set to true (ie. if the combo box is being repopulated)
If bPreventSelectedChange = False Then
' A value was chosen by the user. Reset all other combo box datasources and remove the recently selected value
For Each oCbo As ComboBox In oComboBoxArray
If sender IsNot oCbo Then
PopulateDataSource(oCbo, If(oCbo.SelectedValue = Nothing, 0, oCbo.SelectedValue))
End If
Next
End If
End Sub
End Class

How to search in listview

I am trying to create a Loop that will read through the information on my ListView through the SubItem to find the text that matches the text in my Textbox whenever I hit the search button and Focuses the listbox onto the matched text. Below is what I have but it keeps telling me that the value of string cannot be converted. I am also pretty sure that my numbers wont loop correctly but I am not really sure how to cause them to loop endlessly till end of statement.
Dim T As String
T = Lines.Text
For r As Integer = 0 to -1
For C As Integer = 0 to -1
If List.Items(r).SubItems(C).Text = Lines.Text Then
List.FocusedItem = T
End If
Next
Next
End Sub
I don't understand your code, but I do understand the question. Below is example code to search all rows and columns of a listview. Search is case insensitive and supports a "find next match" scenario. If a match or partial match is found in any column the row is selected. TextBox1 gets the text to find. FindBtn starts a new search.
Private SrchParameter As String = ""
Private NxtStrtRow As Integer = 0
Private Sub FindBtn_Click(sender As Object, e As EventArgs) Handles FindBtn.Click
If Not String.IsNullOrWhiteSpace(TextBox1.Text) Then
SrchParameter = TextBox1.Text
NxtStrtRow = 0
SearchListView()
End If
End Sub
Private Sub ListView1_KeyDown(sender As Object, e As KeyEventArgs) Handles ListView1.KeyDown
If e.KeyCode = Keys.F3 Then
SearchListView()
End If
End Sub
Private Sub SearchListView()
' selects the row containing data matching the text parameter
' sets NxtStrtRow (a form level variable) value for a "find next match" scenario (press F3 key)
If ListView1.Items.Count > 0 Then
If SrchParameter <> "" Then
Dim thisRow As Integer = -1
For x As Integer = NxtStrtRow To ListView1.Items.Count - 1 ' each row
For y As Integer = 0 To ListView1.Columns.Count - 1 ' each column
If InStr(1, ListView1.Items(x).SubItems(y).Text.ToLower, SrchParameter.ToLower) > 0 Then
thisRow = x
NxtStrtRow = x + 1
Exit For
End If
Next
If thisRow > -1 Then Exit For
Next
If thisRow = -1 Then
MsgBox("Not found.")
NxtStrtRow = 0
TextBox1.SelectAll()
TextBox1.Select()
Else
' select the row, ensure its visible and set focus into the listview
ListView1.Items(thisRow).Selected = True
ListView1.Items(thisRow).EnsureVisible()
ListView1.Select()
End If
End If
End If
End Sub
Instead of looping like that through the ListView, try using a For Each instead:
searchstring as String = "test1b"
ListView1.SelectedIndices.Clear()
For Each lvi As ListViewItem In ListView1.Items
For Each lvisub As ListViewItem.ListViewSubItem In lvi.SubItems
If lvisub.Text = searchstring Then
ListView1.SelectedIndices.Add(lvi.Index)
Exit For
End If
Next
Next
ListView1.Focus()
This will select every item which has a text match in a subitem.
Don't put this code in a form load handler, it won't give the focus to the listview and the selected items won't show. Use a Button click handler instead.
This is the easiest way to search in listview and combobox controls in vb net
dim i as integer = cb_name.findstring(tb_name.text) 'findstring will return index
if i = -1 then
msgbox("Not found")
else
msgbox("Item found")
end if