我已将ComboBox绑定到类似的枚举
Enum Foo
Bar
Baz
End Enum
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
FooComboBox.DataSource = [Enum].GetValues(GetType(Foo))
End Sub
我想在给定时间更改所选值
Private Sub FooBar()
FooComboBox.SelectedValue = Foo.Bar
End Sub
但这引发了一个例外:
未处理的类型' System.InvalidOperationException'发生在System.Windows.Forms.dll
中其他信息:无法在ListControl中使用空ValueMember设置SelectedValue。
检查ComboBox我确实可以看到ValueMember
属性为空。但是SelectedValue
等于我读取时当前所选项目的预期值,这表示ValueMember
设置为枚举值与预期一致。
A)如果未设置ValueMember
属性,SelectedValue
中的值来自何处?
B)如果绑定导致SelectedValue
包含正确的值,为什么翻盖不能以相同的方式设置它?
C)我还需要做些什么来使这个血腥的.Net工作?
请注意,确实有不少C#&关于这一点的WPF问题,没有人真正解释这一点,就我所看到的而言,我还没有能够根据建议的答案找出正确的vb语法。 子>
答案 0 :(得分:3)
特别是当值不是连续的时,您需要为控件提供一种方法,将Name“映射”到相关值。将Enum.GetValues
或姓名发布到CBO后,它们就会脱离。
您可以使用KeyValuesPair(of String, Int32)
之类的名称作为TKey,将值作为TValue使用。通用可以使它看起来比它复杂。由于密钥始终为String
,而值通常为 Int32
,因此我倾向于使用简单的NameValuePair
类:
Public Class NameValuePair
Public Property Name As String
Public Property Value As Int32
Public Sub New(n As String, v As Int32)
Name = n
Value = v
End Sub
Public Overrides Function ToString() As String
Return String.Format("{0}", Name)
End Function
End Class
这会将任何名称与任何值相关联。主要是你控制ToString()
的显示。在这种情况下,名称和值都来自Enum;一种创建List或Array数组的简单方法:
Private Enum Stooges
Moe = 9
Larry = 99
Curly = 45
Shemp = 65
CurlyJoe = 8
End Enum
' method to convert any Enum to a collection of Named-Value pairs
Private Function EnumToPairsList(e As Type) As List(Of NameValuePair)
Dim ret As New List(Of NameValuePair)
Dim vals = [Enum].GetValues(e)
Dim names = [Enum].GetNames(e).ToArray
For n As Int32 = 0 To names.Count - 1
ret.Add(New NameValuePair(names(n), CType(vals.GetValue(n), Int32)))
Next
Return ret
End Function
EnumsToPairsList
可以返回数组,也可以根据需要使用KeyValuePair
。它可以扩展为使用Description
代替名称(如果存在)。使用它:
cbox1.DataSource = EnumToPairsList(GetType(Stooges))
cbox1.DisplayMember = "Name" ' use "Key" for a KVP
cbox1.ValueMember = "Value"
' set a value:
cbox1.SelectedValue = Convert.ToInt32(Stooges.Shemp)
由于您已在NVP类中“包装”枚举,因此每个SelectedItem
将包含在Object
中。使用此类DataSource
时,您通常会在SelectedValueChanged
事件中执行操作并检查SelectedValue
。这是它的主要目的:向用户显示名称,但在代码中将枚举值返回给您。
唯一的“诀窍”是它需要被回流到你的枚举:
Private Sub cbox1_SelectedValueChanged(...
Dim eItem As Stooges = CType(cbox1.SelectedValue, Stooges)
Console.WriteLine(eItem)
Console.WriteLine(eItem.ToString)
45
卷曲
如果您坚持使用SelectedItem
,则必须从Object
投射到NameValuePair
,获取值,然后将 投射到您的枚举类型。
保留数据源的副本通常很有用,因此它位于除了作为控制数据源之外的其他位置:
Private StoogesDS As List(Of NameValuePair)
...
StoogesDS = EnumsToPairsList(GetType(Stooges))
cbox1.DataSource = StoogesDS
这允许您的代码即使在表单不在时也仍然使用该集合。如上所述,每个项目现在都是NameValuePair
对象。
cbox1.SelectedItem = StoogesDS.FirstOrDefault(Function(z) z.Name = Stooges.Shemp.ToString())