@H_
301_0@
我已经将Combo
Box绑定到这样的枚举
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
但这引发了一个例外:
An unhandled exception of type ‘System.InvalidOperationException’ occurred in System.Windows.Forms.dll
Additional information: Cannot set the SelectedValue in a ListControl with an empty ValueMember.
检查ComboBox我确实可以看到ValueMember属性为空.但是当我读取时,SelectedValue等于当前所选项目的预期值,这表示ValueMember被设置为预期的枚举值.
A)如果未设置ValueMember属性,SelectedValue中的值来自何处?
B)如果绑定导致SelectedValue包含正确的值,为什么翻盖不能以相同的方式设置它?
C)我还需要做些什么来使这个血腥的.Net工作?
请注意,确实有相当多的C#&关于这一点的WPF问题,没有人真正解释这一点,就我所看到的而言,我无法从建议的答案中找出正确的vb语法.
特别是当值不是连续的时,您需要为控件提供一种
方法,将Name“映射”到相关值.一旦您将Enum.GetValues或
名称发布到CBO,它们就会变得分离.
您可以使用KeyValuesPair(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.它可以扩展为使用描述代替名称.使用它:
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
Curly
如果您坚持使用SelectedItem,则必须从Object转换为NameValuePair,获取Value,然后将其强制转换为Enum Type.
保留数据源的副本通常很有用,因此它位于除了作为控制数据源之外的某个位置:
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())