Don't Add Value If Already Exists In Datagridview - vb.net

I have a "table_info" table with a column for ID,NAME
When Adding new ID,Name. I would like to check if it's already exists. and If it exists, produce a MessageBox.
How can this be done

Ypu have to refer to use rowCell_ID as string because it is the column name in your datagridivew:
Function IsInDatagridview(ByVal cell1 As String, ByVal cell2 As String, ByVal rowCell1_ID As Integer, ByVal rowCell2_ID As Integer, ByRef dgv As DataGridView)
Dim isFound As Boolean = False
For Each rw As DataGridViewRow In dgv.Rows
If rw.Cells("rowCell1_ID" ).Value.ToString = cell1 Then
If rw.Cells("rowCell2_ID" ).Value.ToString = cell2 Then
isFound = True
Return isFound
End If
End If
Next
Return isFound
End Function

There is more than one way to accomplish this. You could check the datasource/set or the actual datagridview itself, if you don't have too many rows. If it's the later then you could do it like so:
Check Function returned true if the criteria is met:
Function IsInDatagridview(ByVal cell1 As String, ByVal cell2 As String, ByVal rowCell1_ID As Integer, ByVal rowCell2_ID As Integer, ByRef dgv As DataGridView)
Dim isFound As Boolean = False
For Each rw As DataGridViewRow In dgv.Rows
If rw.Cells(rowCell1_ID ).Value.ToString = cell1 Then
If rw.Cells(rowCell2_ID ).Value.ToString = cell2 Then
isFound = True
Return isFound
End If
End If
Next
Return isFound
End Function
.
Then to use the Function to display a MessageBox if the criteria is met:
If (IsInDatagridview("id", "name", 0, 1, DataGridView1)) Then
''// Code to display message.
MsgBox("Record Exists!", MsgBoxStyle.Information)
End If
You may need to change The ID to an integer but I reckon it should work. Haven't tested it.
Okay so what this will do is iterate through each row 'rw' within the datagridview you specify, checking for String matches of the cell's columns' and if a match is found 'isFound' is set to true then 'isFound' is returned.

Related

Check the item in ToolStripMenuItem dynamically through Sub Function

I am new to .Net Visual Basic, I am currently self learning and trying to make some small application.
I need a help on Checking a sub menu item of ToolStripMenuItem
Complete concept is like:
I have a datagridview in which user will be able to rearrange the column or make a column visible or Hidded for this I have Sub / Function like below:
Public Sub Fun_Grid_Colomn_Visibility(ByVal GridName As DataGridView, ByRef ColName As String, ByVal MS_col As ToolStripMenuItem, ChkVal As Boolean)
If ChkVal = True Then
With GridName
.Columns("" & ColName & "").Visible = False
End With
MS_col.Checked = False
Exit Sub
End If
If ChkVal = False Then
GridName.Columns("" & ColName & "").Visible = True
MS_col.Checked = True
Exit Sub
End If
End Sub
On the form close I will be saving the user grid format as below (Got code from another Q/A Post) :
Public Sub WriteGrideViewSetting(ByVal dgv As DataGridView, ByVal FileName As String)
Dim settingwriter As XmlTextWriter = New XmlTextWriter("C:\Users\<username>\Desktop\temp\" & FileName & ".xml", Nothing)
settingwriter.WriteStartDocument()
settingwriter.WriteStartElement(dgv.Name)
Dim count As Integer = dgv.Columns.Count
For i As Integer = 0 To count - 1
settingwriter.WriteStartElement("column")
settingwriter.WriteStartElement("Name")
settingwriter.WriteString(dgv.Columns(i).Name)
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("width")
settingwriter.WriteString(dgv.Columns(i).Width.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("headertext")
settingwriter.WriteString(dgv.Columns(i).HeaderText)
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("displayindex")
settingwriter.WriteString(dgv.Columns(i).DisplayIndex.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteStartElement("visible")
settingwriter.WriteString(dgv.Columns(i).Visible.ToString())
settingwriter.WriteEndElement()
settingwriter.WriteEndElement()
Next
settingwriter.WriteEndElement()
settingwriter.WriteEndDocument()
settingwriter.Close()
End Sub
End Module
If the user is reopening the form I used the below (Q/A code) to rearrange Datagridview column as pervious :
Public Sub ReadDataGridViewSetting(ByVal dgv As DataGridView, ByVal FileName As String, ByRef Frm_name As Form)
Dim xmldoc As XmlDocument = New XmlDocument()
Dim xmlnode As XmlNodeList
Dim CMSN_ToolName As String
Dim Var_file_Chk As String = "C:\Users\<user>\Desktop\temp\" & FileName & ".xml"
If System.IO.File.Exists(Var_file_Chk) = True Then
Dim fs As FileStream = New FileStream(Var_file_Chk, FileMode.Open, FileAccess.Read)
xmldoc.Load(fs)
xmlnode = xmldoc.GetElementsByTagName("column")
For i As Integer = 0 To xmlnode.Count - 1
Dim columnName As String = xmlnode(i).ChildNodes.Item(0).InnerText.Trim()
Dim width As Integer = Integer.Parse(xmlnode(i).ChildNodes.Item(1).InnerText.Trim())
Dim headertext As String = xmlnode(i).ChildNodes.Item(2).InnerText.Trim()
Dim displayindex As Integer = Integer.Parse(xmlnode(i).ChildNodes.Item(3).InnerText.Trim())
Dim visible As Boolean = Convert.ToBoolean(xmlnode(i).ChildNodes.Item(4).InnerText.Trim())
dgv.Columns(columnName).Width = width
dgv.Columns(columnName).HeaderText = headertext
dgv.Columns(columnName).DisplayIndex = displayindex
dgv.Columns(columnName).Visible = visible
Next
fs.Close()
End If
End Sub
Now what I need is that a Function or Sub for the Itemmenu. If a Particular column is Visible in the datagridview then the particular Itemmenu should be checked else it would be unchecked. I need this function when Itemmenu is being displayed / opened.
what I tried just (for sample) in Itemmenu opening is like
Private Sub ColumnsToolStripMenuItem_DropDownOpening(sender As Object, e As EventArgs) Handles ColumnsToolStripMenuItem.DropDownOpening
If DGV_CompList.Columns("DGC_Est").Visible = True Then
Dim CMSN_ToolName = MS_CV_Est.Name
Dim unused As ToolStripMenuItem = New ToolStripMenuItem(CMSN_ToolName) With {
.Checked = True
}
End If
End Sub
DGV_CompList -> DataGridView
DGC_Est -> Column Name of datagridview
MS_CV_Est -> - ToolStripMenuItem which need to checked
(Note: I will be changing the MenuItem Name to Match Datagrid Column name for Sync)
But the ToolStripMenuItem is not getting checked.
Actually I need function / Sub where I will be able to pass the grid name and the Menuname and loop through the grid columns and check if the column is visible or not if the particular column is visible then I need to check that item in the itemmenu.
I am requesting for the sub / function because it can be used for any toolstripmenuitem in any form.
Thanks and Regards.
As per #Jimi's hint, assigned each required Menuitem's Tag property with the datagridview column name and created the below sub / function :
Public Sub Fun_ToolStripMenuItem_Check(ByVal dgv As DataGridView, ByVal TS_Menu_Items As ToolStripItemCollection)
For Each item As ToolStripMenuItem In TS_Menu_Items.OfType(Of ToolStripMenuItem)
If Not item.Tag = "" Then
If dgv.Columns(item.Tag).Visible = True Then
item.Checked = True
Else
item.Checked = False
End If
End If
For Each submenu_item As ToolStripMenuItem In item.DropDownItems.OfType(Of ToolStripMenuItem)
If Not submenu_item.Tag = "" Then
If dgv.Columns(submenu_item.Tag).Visible = True Then
submenu_item.Checked = True
Else
submenu_item.Checked = False
End If
End If
Next
Next
End Sub
Note in the loop used - " OfType(Of ToolStripMenuItem) " because I have ToolStripSeparator between the Itemmenus.
On mouse over called the Sub by :
Private Sub MS_ColumnVisible_DropDownOpening(sender As Object, e As EventArgs) Handles MS_ColumnVisible.DropDownOpening
Fun_ToolStripMenuItem_Check(DGV_CompList, MS_CompDGV.Items)
End Sub
'DGV_CompList' - Datagridview Name and 'MS_CompDGV' - ContextMenuStrip Name
More important is that I did not assign any value to the Tag property to Menuitems which are not used show or hide the datagridview columns.

Get OPCItem from ClientHandles in DataChange Event - OPCAutomation.dll

Is it possible to get the OPCItem from a Group using the ClientHandle value?
Pseudo example:
Dim Server As OPCServer
Dim Groups As OPCGroups
Dim WithEvents Group1 as OPCGroup
Dim ItemGroup as OPCItems
Dim Item as OPCItem
Private Sub Form1_Load(sender as Object, e as EventArgs) Handles MyBase.Load
Server.Connect("MyServer")
Group1 = New OPCGroup()
Group1.Name = "Group1"
Group1.IsSubscribed = True
Group1.OPCItems.Add("Item1", 1)
Server.OPCGroups.Add(Group1)
End Sub
Private Sub Group1_DataChange(TransactionID As Integer, NumItems As Integer, ByRef ClientHandles As Array, ByRef ItemValues As Array, ByRef Qualities As Array, ByRef TimeStamps As Array) Handles Group1.DataChange
Dim Browser as OPCBrowser = Server.CreateBrowser()
Browser.ShowBranches()
Browser.DataType = vbInteger
Browser.ShowLeafs()
Dim qualityValue as Integer
For q As Integer = 1 To Qualities.Length
qualityValue = Qualities.GetValue(n)
If qualityValue = 192 Then
'HERE is where I want to get the OPCItem by using the ClientHandles
'I can use the ClientHandle to get the Value, but I'd also like to get the ItemID to do validation against.
Dim itemClientHandle as Integer = Convert.ToInt32(ClientHandles.GetValue(n))
Dim itemValueByClientHandle as String = ItemValues.GetValue(n).ToString()
End If
Next
'It is possible to use the OPCBrowser to get the Item Names but how do I correlate the two?
Dim itemNames as New List(Of String)
For n As Integer = 1 To OPCBrowser.Count
itemNames.Add(OPCBrowser.Item(i))
Next
' Do More Stuff
End Sub
There is a request to enhance an existing client application to be paused when a value is sent from the client to the OPC Server and wait for the bit tag to switch as in indication the process has finished. This part is built; however, there are multiple items (tags) in the group and there needs to be a way of identifying the correct items bit value was changed.

Find rows with CheckBox checked DataGridView

I put some code in to find what checkboxes have been checked in my DataGridView, but for some reason this isn't working.
I have looping through the rows in the DataGridView:
For Each row As DataGridViewRow In dgv_assets.Rows
Next
Then in here i have casted the first column as a DataGridViewCheckBoxCell:
For Each row As DataGridViewRow In dgv_assets.Rows
Dim chk As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
Next
Then I am checking for all the checkboxes that have been checked:
For Each row As DataGridViewRow In dgv_assets.Rows
Dim chk As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
If chk.Value = chk.TrueValue Then
MessageBox.Show("Checked")
End If
Next
For some reason even if the checkboxes are checked or unchecked they all hit the MessageBox.
Your code is almost correct, I guess the casting is the problem.
For Each row As DataGridViewRow In DataGridView1.Rows
Dim chk As DataGridViewCheckBoxCell = row.Cells(Column1.Name)
If chk.Value IsNot Nothing AndAlso chk.Value = True Then
MessageBox.Show("Checked: " + chk.RowIndex.ToString())
End If
Next
Column1 should be the column name of the DataGridViewCheckBoxCell that you are referring.
you can do in that simple way.
For i As Integer = 0 To dtg.RowCount - 1
If dtg.Item(0, i).Value = "True" Then
MsgBox("check")
End If
Next
I hope to be as helpful
Here is an example using a language extension method
Form level variable
Private Const CheckBoxColName As String = "Process"
Place the following in a code module, not a form or class
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function CheckBoxCount(ByVal GridView As DataGridView, ByVal ColumnIndex As Integer, ByVal Checked As Boolean) As Integer
Return (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where CBool(Rows.Cells(ColumnIndex).Value) = Checked).Count
End Function
Use the extension method using the private variable above, CheckBoxColName which is the name of the column in the DataGridView as a DataGridViewCheckBoxColumn
If DataGridView1.CheckBoxCount(CheckBoxColName, True) > 0 Then
Dim Rows = DataGridView1.GetCheckedRows1(CheckBoxColName)
For Each Row In Rows
Console.WriteLine(Row.Cells.Item(1).Value)
Next
End If
If you want to use column index rather than column name the following will do so
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function CheckBoxCount(ByVal GridView As DataGridView, ByVal ColumnIndex As Integer, ByVal Checked As Boolean) As Integer
Return (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where CBool(Rows.Cells(ColumnIndex).Value) = Checked).Count
End Function
Note both allow you to get check or un-checked.
The following gets the actual rows
<System.Diagnostics.DebuggerStepThrough()> _
<Runtime.CompilerServices.Extension()> _
Public Function GetCheckedRows1(ByVal GridView As DataGridView, ByVal ColumnName As String) As List(Of DataGridViewRow)
Dim Temp = (From Rows In GridView.Rows.Cast(Of DataGridViewRow)() Where Not Rows.IsNewRow).ToList
Return (From SubRows In Temp Where CBool(SubRows.Cells(ColumnName).Value) = True).ToList
End Function
you must first verify that TrueValue not null , since according to the documentation , the default is null. And then check if true.
Here Doc : TrueValue
Add CheckBox with Name CK1 And Add DataGridView with Name Dgrd and must the first cell be DataGridViewCheckBoxCell And Add the code:
Private Sub CK1_CheckedChanged(sender As Object, e As EventArgs) Handles CK1.CheckedChanged
If CK1.Checked = True Then
Try
Dim I As Integer
For I = 0 To Dgrd.Rows.Count - 1
Dim CHKRow As DataGridViewCheckBoxCell = Dgrd.Rows(I).Cells(0)
If CHKRow.Value = False Then
CHKRow.Value = True
End If
Next
Catch ex As Exception
End Try
Else
Try
Dim I As Integer
For I = 0 To Dgrd.Rows.Count - 1
Dim CHKRow As DataGridViewCheckBoxCell = Dgrd.Rows(I).Cells(0)
If CHKRow.Value = True Then
CHKRow.Value = False
End If
Next
Catch ex As Exception
End Try
End If
End Sub

Update Dimensional Concurrent Dictionary

I have this little function that I found but I am having a hard time trying to call it correctly. how can I call it to update my ConcurrentDictionary
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Animals As New Concurrent.ConcurrentDictionary(Of String, String())
Dim iKey = "key123456"
Animals(iKey) = {"cat", "dog", "bird"}
Dim success As Boolean = TryUpdate(Animals, iKey, Func("cat", "frog"))
End Sub
Function TryUpdate(Of TKey, TValue)(dict As Concurrent.ConcurrentDictionary(Of TKey, TValue), key As TKey, updateFactory As Func(Of TValue, TValue)) As Boolean
Dim curValue As TValue
If Not dict.TryGetValue(key, curValue) Then
Return False
End If
dict.TryUpdate(key, updateFactory(curValue), curValue)
Return True
End Function
End Class
TryUpdate has three parameters,
the ConcurrentDictionary to be updated,
the Key to be updated in the dictionary, and
a delegate function that accepts the key's current value, and returns the desired value.
Dim success As Boolean = TryUpdate(myDictionary, myKey, Func(oldval) newval)
How you pass the third parameter is up to you, but it looks like the intention is so you can have a look at the old value to ensure it is what you expected, then passing either your new value, or the returned value accordingly.
Addition for clarity: The third parameter is expecting to be passed a delegate to a function which will accept the current value of the key you are trying to change, and return a new value (or the original value, if you don't want to change it).
Here I'm creating a function CheckValue that determines if the old value is what I expected, then if so returns the new value. The myDel is a delegate of that function which is passed into TryUpdate.
Dim whatIExpected As String = ""
Dim newVal As String = ""
Dim myDel As Func(Of String, String) = AddressOf CheckValue
Public Function CheckValue(ByVal oldVal As String) As String
If (oldVal = whatIExpected) Then
Return newVal
Else
Return oldVal
End If
End Function
'Then later inside some function or sub..
whatIExpected = "cat"
newVal = "frog"
Dim success As Boolean = TryUpdate(myDictionary, myKey, myDel)

VB.NET Listview Multiple Column Filter

My goal is to develop a search using multiple textboxes. I have five columns (ArticleNo, Description, PartNum, Manufacturer and Cost) each of which will have a textbox over them.
I keep track of the original list items using:
Private originalListItems As New List(Of ListViewItem)
This is filled with all the items (over 6000).
Then I will have five "text changed" events occuring based on the five textboxes created (tbSearchArticleNo, tbSearchDescription, tbSearchPartNum ... etc)
Private Sub tbSearchArticleNo_TextChanged(sender As Object, e As System.EventArgs) Handles tbSearchArticleNo.TextChanged
If tbSearchDesc.Text <> "" Or tbPartNum.Text <> "" Or tbManufacturer.Text <> "" Or tbCost.Text <> "" Then
SearchCurrentList(lwArticles, tbSearchArticleNo.Text, 0, False)
Else
SearchListView(lwArticles, tbSearchArticleNo.Text, 0, False)
End If
End Sub
Here is my method SearchCurrentList:
Private Sub SearchCurrentList(ByVal listview As ListView, ByVal search As String, ByVal colIndex As Integer, ByVal upperCase As Boolean)
If upperCase Then
search = search.ToUpper()
End If
listview.BeginUpdate()
'Clear listview
lwArticles.Items.Clear()
'Other textbox has information in it, concatenate both results
For Each item In currentListItems
Dim itemToUpper = item.SubItems.Item(colIndex).Text
If upperCase Then
itemToUpper = item.SubItems.Item(colIndex).Text.ToUpper()
End If
If itemToUpper.Contains(search) Then
lwArticles.Items.Add(item)
End If
Next
'Reupdate the current list of items
currentListItems.Clear()
For Each item In lwArticles.Items
currentListItems.Add(item)
Next
listview.EndUpdate()
End Sub
And here is my method SearchListView:
Private Sub SearchListView(ByVal listview As ListView, ByVal search As String, ByVal colIndex As Integer, ByVal upperCase As Boolean)
'Upper case parameter determines if you're searching a string, if so, it is better to compare everything by uppercase
If upperCase Then
search = search.ToUpper()
End If
listview.BeginUpdate()
If search.Trim().Length = 0 Then
'Clear listview
listview.Items.Clear()
'Clear currentListItems
currentListItems.Clear()
'If nothing is in the textbox make all items appear
For Each item In originalListItems
listview.Items.Add(item)
Next
Else
'Clear listview
listview.Items.Clear()
'Clear currentListItems
currentListItems.Clear()
'Go through each item in the original list and only add the ones which contain the search text
For Each item In originalListItems
Dim currItem = item.SubItems.Item(colIndex).Text
If upperCase Then
currItem = currItem.ToUpper()
End If
If currItem.Contains(search) Then
currentListItems.Add(item)
listview.Items.Add(item)
End If
Next
End If
listview.EndUpdate()
End Sub
Here's an example of my search:
tbSearchArticleNo.Text = "33"
This will match every articleNo that contains "33" in the string. Now I want to add another filter:
tbSearchDescription.Text = "Mixer"
This should match everything that contains 33 in the article number as well as "mixer" in the description. And so on and so fourth.
The actual filters are working correctly - my only problem is whenever I erase something, such as "Mixer" (while still having "33" in the articleNo) it doesn't return the results of the articleNo containing "33" ... Instead it doesn't change the results of my search. There might be a better way of searching through this?
A somewhat different way of handling this is to use LINQ. The following function could be used to return an object that enumerates the provided collection including only those items that fit the filter. You could use this enumerator to re-populate your list. If you used originalListItems each time you called GetFilter, you would always have every item included for consideration in the latest filter.
Function GetFilter(source As IEnumerable(Of ListViewItem), articleNo As String, description As String,
partNum As String, prop4 As String, prop5 As String) As IQueryable(Of ListViewItem)
GetFilter = source.AsQueryable
Dim articleFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
Function(i As ListViewItem) i.SubItems(0).Text.IndexOf(articleNo, StringComparison.InvariantCultureIgnoreCase) >= 0
Dim descFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
Function(i As ListViewItem) i.SubItems(1).Text.IndexOf(description, StringComparison.InvariantCultureIgnoreCase) >= 0
Dim partFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
Function(i As ListViewItem) i.SubItems(2).Text.IndexOf(partNum, StringComparison.InvariantCultureIgnoreCase) >= 0
Dim prop4Filter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
Function(i As ListViewItem) i.SubItems(3).Text.IndexOf(prop4, StringComparison.InvariantCultureIgnoreCase) >= 0
Dim prop5Filter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
Function(i As ListViewItem) i.SubItems(4).Text.IndexOf(prop5, StringComparison.InvariantCultureIgnoreCase) >= 0
If Not String.IsNullOrEmpty(articleNo) Then GetFilter = Queryable.Where(GetFilter, articleFilter)
If Not String.IsNullOrEmpty(description) Then GetFilter = Queryable.Where(GetFilter, descFilter)
If Not String.IsNullOrEmpty(partNum) Then GetFilter = Queryable.Where(GetFilter, partFilter)
If Not String.IsNullOrEmpty(prop4) Then GetFilter = Queryable.Where(GetFilter, prop4Filter)
If Not String.IsNullOrEmpty(prop5) Then GetFilter = Queryable.Where(GetFilter, prop5Filter)
End Function
Better yet, with a little more thought, you could probably make articleNo and the other parameters into variables with a larger scope, and adjust the function to embed IsNullOrEmpty checking into the Queryable expression, and then you wouldn't need to even re-generate the filter when a field value changes. You could just set the variable to the new textbox value and re-evaluate the already-generated filter expression, which will consider the new values in the variables thus yielding newly filtered results.
Here's how I would expect it to be used:
lwArticles.Items.Clear()
For Each i In GetFilter(originalListItems, tbSearchArticleNo.Text, tbSearchDesc.Text, tbPartNum.Text, tbManufacturer.Text, tbCost.Text)
lwArticles.Items.Add(i)
Next
Instead of only filtering one column at a time and passing the current list in to further filter the results, how about having a single function that filters based on all the specified values at once:
Call a single "Filter" function from the TextChanged (or Validated) event of every filter Textbox.
In the Filter function, start by re-copying originalListItems into lwArticles.
Apply filters for each Textbox that has a value in sequence. (Call SearchCurrentList for each textbox, passing in lwArticles. Each step filters down the list further from the previous, but only doing work for textboxes that have values.)
Its hard to follow what you are trying to do, but i suggest if you are dealing with 6k items in a listview and want to filter them, perhaps you should use a databound gridview instead.
Then you can perform the search on the datasource, very simply:
Public Class Form1
Private _articleList As List(Of Article)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'populate _itemList somehow, for example from a database. Manually here for example purposes:
_articleList = New List(Of Article) From {
New Article("jenny cooks fish", "cooking"),
New Article("a better sales team", "sales")}
DataGridView1.DataSource = _articleList
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim filtered As List(Of Article) = _articleList.Where(Function(x) x.Title.Contains("cook") AndAlso x.Category = "cooking").ToList
DataGridView1.DataSource = filtered
End Sub
End Class
Public Class Article
Property Title As String
Property Category As String
'etc etc
Public Sub New(ByVal title As String, ByVal category As String)
_Title = title
_Category = category
End Sub
End Class
I managed to get it to work. For those wondering how, it's not that elegant - but it works!
I set tags on the GUI of the four textboxes (i omitted the cost textbox after further talk with the engineers). So..
tbSearchArticleNo.Tag = 1
tbSearchDesc.Tag = 2
tbPartNum.Tag = 4
tbManufacturer.Tag = 8
This isn't elegant because you will exponentially grow as you add textboxes. (be careful) Depending on the fields entered, a total is calculated which will then be treated by my FilterOriginalList(total)
Private Sub tbSearchArticleNo_TextChanged(sender As Object, e As System.EventArgs) Handles tbSearchArticleNo.TextChanged, tbSearchDesc.TextChanged, tbPartNum.TextChanged, tbManufacturer.TextChanged
Dim tag1 As Integer = 0
Dim tag2 As Integer = 0
Dim tag3 As Integer = 0
Dim tag4 As Integer = 0
If tbSearchArticleNo.Text <> "" Then
tag1 = tbSearchArticleNo.Tag
End If
If tbSearchDesc.Text <> "" Then
tag2 = tbSearchDesc.Tag
End If
If tbPartNum.Text <> "" Then
tag3 = tbPartNum.Tag
End If
If tbManufacturer.Text <> "" Then
tag4 = tbManufacturer.Tag
End If
FilterOriginalList(tag1 + tag2 + tag3 + tag4)
End Sub
Here is my method:
Private Sub FilterOriginalList(ByRef tagCounter As Integer)
Dim field1 As String = tbSearchArticleNo.Text
Dim field2 As String = tbSearchDesc.Text.ToUpper()
Dim field4 As String = tbPartNum.Text.ToUpper()
Dim field8 As String = tbManufacturer.Text.ToUpper()
lwArticles.BeginUpdate()
'Clear listview
lwArticles.Items.Clear()
For Each item In originalListItems
Dim currField1 = item.SubItems.Item(0).Text
Dim currField2 = item.SubItems.Item(1).Text.ToUpper
Dim currField4 = item.SubItems.Item(2).Text.ToUpper
Dim currField8 = item.SubItems.Item(3).Text.ToUpper
Select Case (tagCounter)
Case 0
lwArticles.Items.Add(item)
Case 1
If currField1.Contains(field1) Then
lwArticles.Items.Add(item)
End If
Case 2
If currField2.Contains(field2) Then
lwArticles.Items.Add(item)
End If
Case 3
If currField1.Contains(field1) And currField2.Contains(field2) Then
lwArticles.Items.Add(item)
End If
Case 4
If currField4.Contains(field4) Then
lwArticles.Items.Add(item)
End If
Case 5
If currField1.Contains(field1) And currField4.Contains(field4) Then
lwArticles.Items.Add(item)
End If
Case 6
If currField2.Contains(field2) And currField4.Contains(field4) Then
lwArticles.Items.Add(item)
End If
Case 7
If currField1.Contains(field1) And currField2.Contains(field2) And currField4.Contains(field4) Then
lwArticles.Items.Add(item)
End If
Case 8
If currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 9
If currField1.Contains(field1) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 10
If currField2.Contains(field2) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 11
If currField1.Contains(field1) And currField2.Contains(field2) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 12
If currField4.Contains(field4) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 13
If currField1.Contains(field1) And currField4.Contains(field4) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 14
If currField2.Contains(field2) And currField4.Contains(field4) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
Case 15
If currField1.Contains(field1) And currField2.Contains(field2) And currField4.Contains(field4) And currField8.Contains(field8) Then
lwArticles.Items.Add(item)
End If
End Select
Next
lwArticles.EndUpdate()
End Sub
Thanks for everyone who helped. Here's the solution I found - there's probably something much easier that I will be looking into in the futur!