I'm trying to filter list datagridview via textbox using a second bindinglist class and set to bindingsource.datasource in vb.net.
The problem is when I filter in two event textboxes and then I I make clear or blank in one of the textboxes then the state of datagridview is not in the state in the filter.
RESULT FILTER WITH BINDINGLIST
Should be when I clear in textbox criteria2 then datagridview should keep filter state referring to textbox criteria1 as below screenshot should keep filter in criteria1 A
.
Is there something wrong with my code?
Class SortableBindingList
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
''' <summary>
''' Provides a generic collection that supports data binding and additionally supports sorting.
''' See http://msdn.microsoft.com/en-us/library/ms993236.aspx
''' If the elements are IComparable it uses that; otherwise compares the ToString()
''' </summary>
''' <typeparam name="T">The type of elements in the list.</typeparam>
Public Class SortableBindingList(Of T As Class)
Inherits BindingList(Of T)
Private _isSorted As Boolean
Private _sortDirection As ListSortDirection = ListSortDirection.Ascending
Private _sortProperty As PropertyDescriptor
''' <summary>
''' Initializes a new instance of the <see cref="SortableBindingList{T}"/> class.
''' </summary>
Public Sub New()
End Sub
''' <summary>
''' Initializes a new instance of the <see cref="SortableBindingList{T}"/> class.
''' </summary>
''' <param name="list">An <see cref="T:System.Collections.Generic.IList`1" /> of items to be contained in the <see cref="T:System.ComponentModel.BindingList`1" />.</param>
Public Sub New(ByVal list As IList(Of T))
MyBase.New(list)
End Sub
''' <summary>
''' Gets a value indicating whether the list supports sorting.
''' </summary>
Protected Overrides ReadOnly Property SupportsSortingCore As Boolean
Get
Return True
End Get
End Property
''' <summary>
''' Gets a value indicating whether the list is sorted.
''' </summary>
Protected Overrides ReadOnly Property IsSortedCore As Boolean
Get
Return _isSorted
End Get
End Property
''' <summary>
''' Gets the direction the list is sorted.
''' </summary>
Protected Overrides ReadOnly Property SortDirectionCore As ListSortDirection
Get
Return _sortDirection
End Get
End Property
''' <summary>
''' Gets the property descriptor that is used for sorting the list if sorting is implemented in a derived class; otherwise, returns null
''' </summary>
Protected Overrides ReadOnly Property SortPropertyCore As PropertyDescriptor
Get
Return _sortProperty
End Get
End Property
''' <summary>
''' Removes any sort applied with ApplySortCore if sorting is implemented
''' </summary>
Protected Overrides Sub RemoveSortCore()
_sortDirection = ListSortDirection.Ascending
_sortProperty = Nothing
_isSorted = False
End Sub
''' <summary>
''' Sorts the items if overridden in a derived class
''' </summary>
''' <param name="prop"></param>
''' <param name="direction"></param>
Protected Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
_sortProperty = prop
_sortDirection = direction
Dim list As List(Of T) = TryCast(Items, List(Of T))
If list Is Nothing Then
Return
End If
list.Sort(AddressOf Compare)
_isSorted = True
'fire an event that the list has been changed.
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Private Function Compare(ByVal lhs As T, ByVal rhs As T) As Integer
Dim result = OnComparison(lhs, rhs)
'invert if descending
If _sortDirection = ListSortDirection.Descending Then
result = -result
End If
Return result
End Function
Private Function OnComparison(ByVal lhs As T, ByVal rhs As T) As Integer
Dim lhsValue As Object = If(lhs Is Nothing, Nothing, _sortProperty.GetValue(lhs))
Dim rhsValue As Object = If(rhs Is Nothing, Nothing, _sortProperty.GetValue(rhs))
If lhsValue Is Nothing Then
Return If(rhsValue Is Nothing, 0, -1) 'nulls are equal
End If
If rhsValue Is Nothing Then
Return 1 'first has value, second doesn't
End If
If TypeOf lhsValue Is IComparable Then
Return DirectCast(lhsValue, IComparable).CompareTo(rhsValue)
End If
If lhsValue.Equals(rhsValue) Then
Return 0 'both are the same
End If
'not comparable, compare ToString
Return lhsValue.ToString().CompareTo(rhsValue.ToString())
End Function
End Class
Public Class Form4
Private StockCardsCache As List(Of StockCards)
Private _criteriasBindingList As New SortableBindingList(Of StockCards)()
Private bindingSource As BindingSource = Nothing
Private Sub LoadData()
StockCardsCache = New List(Of StockCards) From {
New StockCards() With {
.Invono = "PI0001",
.InvoDate = New DateTime(2024, 2, 1),
.Transaction = "PURCHASE",
.CodeProduct = "TEST 1000",
.Barcode = "1000",
.Criteria1 = "A",
.Criteria2 = "C",
.Criteria3 = "E",
.Criteria4 = "G",
.IN = 10,
.OUT = 0,
.BLC = 10
},
New StockCards() With {
.Invono = "PI0001",
.InvoDate = New DateTime(2024, 2, 1),
.Transaction = "PURCHASE",
.CodeProduct = "TEST 1000",
.Barcode = "1000",
.Criteria1 = "B",
.Criteria2 = "D",
.Criteria3 = "F",
.Criteria4 = "H",
.IN = 12,
.OUT = 0,
.BLC = 22
},
New StockCards() With {
.Invono = "PI0001",
.InvoDate = New DateTime(2024, 2, 1),
.Transaction = "PURCHASE",
.CodeProduct = "TEST 1000",
.Barcode = "1000",
.Criteria1 = "A",
.Criteria2 = "E",
.Criteria3 = "G",
.Criteria4 = "I",
.IN = 12,
.OUT = 0,
.BLC = 34
},
New StockCards() With {
.Invono = "PI0001",
.InvoDate = New DateTime(2024, 2, 1),
.Transaction = "PURCHASE",
.CodeProduct = "TEST 1000",
.Barcode = "1000",
.Criteria1 = "B",
.Criteria2 = "F",
.Criteria3 = "H",
.Criteria4 = "J",
.IN = 12,
.OUT = 0,
.BLC = 46
}
}
_criteriasBindingList = New SortableBindingList(Of StockCards)(StockCardsCache)
bindingSource = New BindingSource With {.DataSource = _criteriasBindingList}
DataGridView1.DataSource = bindingSource
End Sub
Private Sub Form4_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadData()
End Sub
Private Sub txtcriteria1_TextChanged(sender As Object, e As EventArgs) Handles txtcriteria1.TextChanged
Dim str = txtcriteria1.Text.Trim().ToLower()
bindingSource.DataSource = If(String.IsNullOrEmpty(str), _criteriasBindingList, _criteriasBindingList.Where(Function(c) c.Criteria1.ToLower().Contains(str)).ToList())
End Sub
Private Sub txtcriteria2_TextChanged(sender As Object, e As EventArgs) Handles txtcriteria2.TextChanged
Dim str = txtcriteria2.Text.Trim().ToLower()
bindingSource.DataSource = If(String.IsNullOrEmpty(str), _criteriasBindingList, _criteriasBindingList.Where(Function(c) c.Criteria2.ToLower().Contains(str)).ToList())
End Sub
End Class
Your code of
Private Sub txtcriteria1_TextChanged(sender As Object, e As EventArgs) Handles txtcriteria1.TextChanged
Dim str = txtcriteria1.Text.Trim().ToLower()
bindingSource.DataSource = If(String.IsNullOrEmpty(str), _criteriasBindingList, _criteriasBindingList.Where(Function(c) c.Criteria1.ToLower().Contains(str)).ToList())
End Sub
Private Sub txtcriteria2_TextChanged(sender As Object, e As EventArgs) Handles txtcriteria2.TextChanged
Dim str = txtcriteria2.Text.Trim().ToLower()
bindingSource.DataSource = If(String.IsNullOrEmpty(str), _criteriasBindingList, _criteriasBindingList.Where(Function(c) c.Criteria2.ToLower().Contains(str)).ToList())
End Sub
does the following:
Instead, implement a filtering function, like:
Private Sub myFilter(str1 As String, str2 As String)
If (String.IsNullOrEmpty(str1) AndAlso String.IsNullOrEmpty(str2)) Then
bindingSource.DataSource = _criteriasBindingList
Else If (String.IsNullOrEmpty(str1)) Then
bindingSource.DataSource = _criteriasBindingList.Where(Function(c) c.Criteria2.ToLower().Contains(str2)).ToList()
Else If (String.IsNullOrEmpty(str2)) Then
bindingSource.DataSource = _criteriasBindingList.Where(Function(c) c.Criteria1.ToLower().Contains(str1)).ToList()
Else
bindingSource.DataSource = _criteriasBindingList.Where(Function(c) c.Criteria1.ToLower().Contains(str1) AndAlso c.Criteria2.ToLower().Contains(str2)).ToList()
End If
End Sub
All in all, you will need to apply each and every criteria that's applicable.