按属性搜索BindingList

时间:2016-07-02 11:36:54

标签: .net vb.net class bindinglist

我的程序中有一个bindingList,我想添加一些元素。元素是类 NameValue_Client 的一些实例,其中包含三个属性。我想使用我想要的任何属性搜索列表。

这是班级:

Public Class NameValue_Client
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Private _assigned_db_name As String, _assigned_tcp_name As String
    Private _val_obj As Client
    Private _key_obj As Integer


    Public WriteOnly Property DB_Name As String
        Set(ByVal value As String)
            _assigned_db_name = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("DB_Name"))
        End Set
    End Property

    Public Property Value As Client
        Get
            Return _val_obj
        End Get
        Set(ByVal value As Client)
            _val_obj = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Value"))
        End Set
    End Property

    Public Property Key As Integer
        Get
            Return _key_obj
        End Get
        Set(ByVal value As Integer)
            _key_obj = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Key"))
        End Set
    End Property

    Public ReadOnly Property Name_Identifier As String
        Get
            Return String.Format("{0} : {1}", _assigned_db_name, _assigned_tcp_name)
        End Get
    End Property



    Sub New(ByVal Key As Integer, ByVal DB_Name As String)
        _assigned_db_name = DB_Name
        _key_obj = Key
    End Sub

    Private Sub changed(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Handles Me.PropertyChanged
        If e.PropertyName = "Value" Then
            If _val_obj IsNot Nothing Then
                _assigned_tcp_name = _val_obj.Details.Computer_Name
            End If
        End If
    End Sub

    Public Overrides Function ToString() As String
        If _val_obj IsNot Nothing Then
            Return String.Format("Db_Name:{0} Tcp_Name:{1} {2}", _assigned_db_name, _assigned_tcp_name, _val_obj.ToString)
        Else
            Return String.Format("Db_Name:{0} Tcp_Name:{1} Nothing", _assigned_db_name, _assigned_tcp_name)
        End If
    End Function
End Class

我在MSDN上找到了这个,它看起来是解决方案,但它只针对一个属性而且我不想放一个选择案例。它必须是一种更好的方式。

这是我找到的代码:

Public Class MyFontList
    Inherits BindingList(Of Font)

    Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
        Get
            Return True
        End Get
    End Property

    Protected Overrides Function FindCore(ByVal prop As PropertyDescriptor, _
        ByVal key As Object) As Integer
        ' Ignore the prop value and search by family name.<--That's why
        Dim i As Integer
        While i < Count
            If Items(i).FontFamily.Name.ToLower() = CStr(key).ToLower() Then
                Return i
            End If
            i += 1
        End While

        Return -1
    End Function
End Class

而且我不知道如何实施这个孩子&#39; class(从未使用过这种类型)。

这是我的代码(直到现在):

Public Class NameValue_Client
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Private _assigned_db_name As String, _assigned_tcp_name As String
    Private _val_obj As Client
    Private _key_obj As Integer


    Public WriteOnly Property DB_Name As String
        Set(ByVal value As String)
            _assigned_db_name = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("DB_Name"))
        End Set
    End Property

    Public Property Value As Client
        Get
            Return _val_obj
        End Get
        Set(ByVal value As Client)
            _val_obj = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Value"))
        End Set
    End Property

    Public Property Key As Integer
        Get
            Return _key_obj
        End Get
        Set(ByVal value As Integer)
            _key_obj = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Key"))
        End Set
    End Property

    Public ReadOnly Property Name_Identifier As String
        Get
            Return String.Format("{0} : {1}", _assigned_db_name, _assigned_tcp_name)
        End Get
    End Property



    Sub New(ByVal Key As Integer, ByVal DB_Name As String)
        _assigned_db_name = DB_Name
        _key_obj = Key
    End Sub

    Private Sub changed(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Handles Me.PropertyChanged
        If e.PropertyName = "Value" Then
            If _val_obj IsNot Nothing Then
                _assigned_tcp_name = _val_obj.Details.Computer_Name
            End If
        End If
    End Sub

    Public Overrides Function ToString() As String
        If _val_obj IsNot Nothing Then
            Return String.Format("Db_Name:{0} Tcp_Name:{1} {2}", _assigned_db_name, _assigned_tcp_name, _val_obj.ToString)
        Else
            Return String.Format("Db_Name:{0} Tcp_Name:{1} Nothing", _assigned_db_name, _assigned_tcp_name)
        End If
    End Function
End Class

Public Class Interface_NameValue
    Inherits BindingList(Of NameValue_Client)

    Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
        Get
            Return True
        End Get
    End Property

    Protected Overrides Function FindCore(ByVal prop As PropertyDescriptor, _
        ByVal key As Object) As Integer

        ' Ignore the prop value and search by family name.
        Dim i As Integer

        While i < Count
            ''Old-fashion way
            Select Case prop.Name
                Case "Value"
                Case "Key"
                Case "Name_Identifier"
            End Select
            i += 1
        End While

        Return -1
    End Function
End Class

现在我应该怎么做这个新课程?我该如何实现呢?

1 个答案:

答案 0 :(得分:1)

I want to search through the list using any property I want...and I don't want to put a select case .

来自MSDN的MyFontList类显示了您将如何实现集合 - 注意Inherits BindingList(Of Font) - 而不是修改项< / em> class(NameValue_Client)。您的代码将使用该类代替BindingList(of NameValue_Client)集合变量。

有一种更简单的方法。

首先,虽然您的商品类没有理由订阅自己的PropertyChanged事件。只需将Value setter更改为:

Set(ByVal value As Client)
    _val_obj = value
    If _val_obj IsNot Nothing Then
        _assigned_tcp_name = _val_obj.ComputerName
    End If
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Value"))
End Set

举起事件之前更新_assigned_tcp_name 将允许新的值对订阅该事件的任何内容可见,并且可能使用Name_Identifier。但是你应该考虑摆脱_assigned_tcp_name,因为它允许它变得过时&#34;陈旧&#34;:

Public ReadOnly Property Name_Identifier As String
    Get
        Dim tcpname = If(Value IsNot Nothing, Value.ComputerName, "")
        Return String.Format("{0} : {1}", _assigned_db_name, tcpname)
    End Get
End Property

KeyValuePair类型的类似乎很奇怪,其中Value基本上是可选的(显然是手动设置的)。它甚至根本不存在,因此可以Key没有Value

在搜索方面,项目类中只有一个属性:KeyValue是一种类型,这意味着您可能需要Client上的任意数量的属性之一。 DB_Name是WriteOnly(?!),因此无法搜索;我想你可能会搜索Name_Identifier,但这是一个复合词,&#39; artificial&#39;属性。

我们只能在Client上看到1个属性,所以我添加了一些用于说明目的:

Public Class Client
    Public Property ComputerName As String
    Public Property Foo As String
    Public Property Bar As Int32

    Public Sub New(n As String)
        ComputerName = n
    End Sub
End Class

您可以使用linq找到您想要的任何内容:

Dim Clients As New BindingList(Of NameValue_Client)

Dim c = New Client("ziggy") With {.Bar = 9, .Foo = "9"}
Dim NVC = New NameValue_Client(1, "Alpha")
NVC.Value = c
Clients.Add(NVC)

c = New Client("zoey") With {.Bar = 7, .Foo = "Q"}
NVC = New NameValue_Client(2, "Beta")  With {.Value = c}
Clients.Add(NVC)

' find a key:
NVC = Clients.FirstOrDefault(Function(q) q.Key = 1)
' find a client object:
NVC = Clients.FirstOrDefault(Function(q) q.Value Is c)
' find a client.computername:
NVC = Clients.FirstOrDefault(Function(q) q.Value.ComputerName = "Mine")
' find a client.foo value
NVC = Clients.FirstOrDefault(Function(q) q.Value.Foo = "Q")

' return is Nothing if not found:
If NVC Is Nothing Then
    ' NOT FOUND!
Else
    ' found
    Console.WriteLine(NVC.Name_Identifier)
End If

您搜索的内容可以是变量,但当然,搜索Key(int)需要int var,其他属性可能需要stringDateTime变量。

如上所述,如果无法找到您想要的内容,FirstOrDefault将无效。如第二个示例中那样搜索Client对象将要求c与列表中的对象完全相同。即使具有相同属性值的其他客户端对象也不匹配。如果您需要,可以实现自己的比较器。

由于Value可以是Nothing,任何涉及它的查询都应该考虑到这一点:

NVC = Clients.
        FirstOrDefault(Function(q) q.Value IsNot Nothing AndAlso
                                 q.Value.Foo = "Q")

项目类中的某些代码也应允许这样做,或者更改它以便在没有Client对象的情况下无法创建项目。