如何为绑定自定义组合框获取第二个ValueMember



我有一个简单的自定义组合框,它只添加了一个属性"ValueMember2"

我已将组合框数据源添加到数据集

我可以在代码中设置属性,就像设置普通属性&;valumember &;

一样
cboRadioType.ValueMember = "ID"
cboRadioType.ValueMember2 = "FREQMIN"
cboRadioType.DisplayMember = "MODEL"

ValueMember属性将返回来自数据源的ID新的valuemember属性只返回字符串"FREQMIN">

我的自定义组合框代码如下:

Imports System.ComponentModel
Public Class NewCBO
Inherits ComboBox
Dim vm2 As String
<Description("Gets/Sets the ValueMember2 of Control")>
Property ValueMember2() As String
Get
ValueMember2 = vm2
End Get
Set(ByVal Value As String)
vm2 = Value
End Set
End Property
End Class

我需要改变我的自定义属性,使其从连接的数据源返回值?所有的搜索都显示了如何"显示valumember">

这是一个自定义的ComboBox类,其中包括基于现有ValueMemberSelectedValue实现的相当严格的ValueMember2SelectedValue2实现:

Imports System.ComponentModel
Public Class ComboBoxEx
Inherits ComboBox
Private _valueMember2 As BindingMemberInfo
Public Property ValueMember2 As String
Get
Return _valueMember2.BindingMember
End Get
Set(value As String)
If value Is Nothing Then
value = String.Empty
End If
Dim bindingMemberInfo As New BindingMemberInfo(value)
If bindingMemberInfo.Equals(_valueMember2) Then
Return
End If
'This part is implemented in ValueMember but cannot be here because SetDataConnection is Private.
'It may be possible to provide our own implement of SetDataConnection but that is not done here.
'If DisplayMember.Length = 0 Then
'    SetDataConnection(DataSource, bindingMemberInfo, False)
'End If
'This part is implemented in ValueMember but cannot be here because BindingMemberInfoInDataManager is Private.
'It may be possible to provide our own implement of BindingMemberInfoInDataManager but that is not done here.
'If DataManager IsNot Nothing AndAlso
'   value <> String.Empty AndAlso
'   Not BindingMemberInfoInDataManager(bindingMemberInfo) Then
'    Throw New ArgumentException("...", NameOf(value))
'End If
_valueMember2 = bindingMemberInfo
'A rigorous implementation should also include implementation of corresponding events.
'OnValueMember2Changed(EventArgs.Empty)
'OnSelectedValue2Changed(EventArgs.Empty)
End Set
End Property
Public Property SelectedValue2 As Object
Get
Return If(SelectedIndex <> -1 AndAlso DataManager IsNot Nothing,
FilterItemOnProperty(DataManager.List(SelectedIndex), _valueMember2.BindingField),
Nothing)
End Get
Set(value As Object)
If DataManager Is Nothing Then
Return
End If
Dim bindingField = _valueMember2.BindingField
If String.IsNullOrEmpty(bindingField) Then
Throw New InvalidOperationException("...")
End If
'This part is implemented in ValueMember but cannot be here because DataManager.Find is Private.
'SelectedIndex = DataManager.Find(DataManager.GetItemProperties().Find(bindingField, True), value, True)
'The following replaces the call to DataManager.Find above.
If value Is Nothing Then
Throw New ArgumentNullException(NameOf(value))
End If
Dim newSelectedIndex = -1
Dim [property] = DataManager.GetItemProperties().Find(bindingField, True)
If [property] IsNot Nothing Then
Dim list=DataManager.List
Dim bindingList = TryCast(list, IBindingList)
If bindingList?.SupportsSearching Then
newSelectedIndex = bindingList.Find([property], value)
Else
For i = 0 To list.Count - 1
Dim obj = list(i)
If value.Equals(obj) Then
newSelectedIndex = i
Exit For
End If
Next
End If
End If
SelectedIndex = newSelectedIndex
End Set
End Property
End Class

里面有一些你应该读的笔记。还要注意,ValueMember具有ValueMember2所缺乏的设计时支持。使用相同的编辑器可能并不难,但我没有研究过。同样值得注意的是,ValueMemberSelectedValue是在ListControl中实现的,因此也被ListBox继承。您必须在自定义ListBox中单独实现此代码。

我用下面的代码测试了这个控件:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim table As New DataTable
With table.Columns
.Add("Id", GetType(Integer))
.Add("Name", GetType(String))
.Add("DateOfBirth", GetType(Date))
End With
With table.Rows
.Add(1, "Peter", #1/1/2001#)
.Add(2, "Paul", #2/2/2002#)
.Add(3, "Mary", #3/3/2003#)
End With
BindingSource1.DataSource = table
With ComboBoxEx1
.DisplayMember = "Name"
.ValueMember = "Id"
.ValueMember2 = "DateOfBirth"
.DataSource = BindingSource1
End With
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show($"ID: {ComboBoxEx1.SelectedValue}; Date of Birth: {ComboBoxEx1.SelectedValue2}", ComboBoxEx1.Text)
End Sub
End Class

它完全按照预期工作。相同的代码也应该适用于其他数据源,例如List(Of T),尽管我没有做任何额外的测试。

只是发布我的发现。不知道这是不是正确的方式,但它工作。

我在自定义控件中添加了以下内容:

Dim mds As New DataTable

然后在属性中我改成了:

<Description("Gets/Sets the ValueMember2 of Control")>
Property ValueMember2() As String
Get
mds = Me.DataSource
ValueMember2 = mds.Rows(Me.SelectedValue - 1).Item(vm2)
End Get
Set(ByVal Value As String)
vm2 = Value
End Set
End Property

我不知道为什么我必须做-1,但它像一个魅力。

在正常代码中,而不是组合框。selectedvalue我用的是组合框。valuember2,它返回正确的项。

最新更新