我一直在一遍又一遍地尝试让我的ComboBox
项目正确排序,但我做的似乎都不起作用。我已经看了许多SO主题,并提出了各种建议,但无论我如何尝试,每次加载表单时,ComboBox
中的项都不会排序。下面是我用来填充ComboBox
的基本代码:
'ClaimCodes is a class-level variable
Private ClaimCodes As DataTable
Private Sub LoadCodeComboBoxes()
Dim CodeTable As DataTable
Dim DescriptionTable As DataTable
Dim DescriptionBinding As New BindingSource
Dim CodeBinding As New BindingSource
Using MyDB As New DbConnection("my connection string")
ClaimCodes = MyDB.ExecuteStatement("SELECT code, descr FROM code_table WHERE code > 0")
End Using
CodeTable = ClaimCodes.Copy
CodeTable.DefaultView.Sort = "code ASC"
CodeTable = CodeTable.DefaultView.ToTable
DescriptionTable = ClaimCodes.Copy
DescriptionTable.DefaultView.Sort = "descr ASC"
DescriptionTable = DescriptionTable.DefaultView.ToTable
CodeBinding.DataSource = CodeTable
CodeBinding.Sort = "code"
DescriptionBinding.DataSource = DescriptionTable
DescriptionBinding.Sort = "descr"
With Me.cboClaimCode
.DataSource = Nothing
.Items.Clear()
.DataSource = CodeBinding
.ValueMember = "code"
.DisplayMember = "code"
.AutoCompleteSource = AutoCompleteSource.ListItems
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.SelectedIndex = -1
End With
With Me.cboClaimCodeDescription
.DataSource = Nothing
.Items.Clear()
.DataSource = DescriptionBinding
.ValueMember = "code"
.DisplayMember = "descr"
.AutoCompleteSource = AutoCompleteSource.ListItems
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.SelectedIndex = -1
End With
End Sub
我已经尝试了上述的各种迭代,包括:
- 完全删除了
BindingSource
对象并直接使用了XXXTable.DefaultView
- 在
DataTable
级别、BindingSource
级别或两者上应用Sort
- 将
ComboBox
的SelectedIndex
属性更改为显示项目,而不是将其设置为-1
(x) - 更改
ComboBox
属性设置的顺序,使DataSource
设置在ValueMember
和DisplayMember
之前/之后 - 将
ComboBox
的.Sorted
属性设置为true(* 当然,这会引发异常,因为对象绑定到DataSource
*)
ClaimCodes
DataTable
(* 在应用任何排序之前 *)有17行:
+---------------------+
| code | descr |
+---------------------+
| 10 | <code desc> |
| 11 | <code desc> |
| 13 | <code desc> |
| 14 | <code desc> |
| 15 | <code desc> |
| 30 | <code desc> |
| 35 | <code desc> |
| 99 | <code desc> |
| 1 | <code desc> |
| 36 | <code desc> |
| 54 | <code desc> |
| 60 | <code desc> |
| 29 | <code desc> |
| 61 | <code desc> |
| 50 | <code desc> |
| 71 | <code desc> |
| 70 | <code desc> |
+---------------------+
应用排序后,我可以检查对象(* DataTable
和/或BindingSource
*),并在Watch窗口中查看结果。从那里,它们显示为预期的排序(*1,10,11等 *)。但是,当显示表单时,ComboBox
中的项目 * 未 * 排序,并以与原始未排序的DataTable
相同的顺序显示(*10,11,13等 *)。
下面是我从SO问题中寻找灵感的几个例子:
- Sort string items in a datatable as int using c#(* 并不真正适用B/c我已经验证了这些值作为
System.Int32
* 存储在DataTable
中) - Sort the items in the combobox in vb net
- Sort combobox items from datasource (GetScheme("Tables")
- how to sort data in my combobox
- Sort combobox alphabetically
- how to sorting item in combo box by Alphabet
我觉得我可能忽略了一些非常简单/愚蠢的事情,但我已经一遍又一遍地没有进展,也不知道为什么。我做错了什么?
还有一件事,我刚刚想到,这可能与此有关:这些ComboBox
es具有以下属性:
*绘图模式:OwnerDrawFixed
*下拉样式:DropDownList
*FlatStyle:System
*已启用加密:True
不确定OwnerDrawFixed
是否与此有关,但我使用它来实现一个自定义的.DrawItem
事件处理程序,以便在选择ComboBox
时突出显示它。
快速更新:
我将其中一个ComboBox
es上的DrawMode
切换回Normal
并再次尝试,但项目仍然“未排序”。这似乎不是问题的原因。
附加代码:
如前所述,我正在为ComboBox
es使用一个自定义的DrawItem
处理程序,以便在选择它时进行视觉样式化。下面是该事件处理程序的代码,它基本上在每个ComboBox
es上重用:
Private Sub cboClaimCode_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles cboClaimCode.DrawItem
Dim ComboBox As ComboBox = TryCast(sender, ComboBox)
Dim ComboBoxFont As Font = ComboBox.Font
Dim ComboBoxColor As Color
Dim TextColor As Color
Dim ComboBoxBounds As Rectangle = e.Bounds
Dim TextBrush As SolidBrush
Dim ComboBoxBrush As SolidBrush
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
TextColor = SystemColors.WindowText
ComboBoxColor = Colors.PaleBlue
Else
TextColor = SystemColors.WindowText
ComboBoxColor = SystemColors.Window
End If
TextBrush = New SolidBrush(TextColor)
ComboBoxBrush = New SolidBrush(ComboBoxColor)
e.Graphics.FillRectangle(ComboBoxBrush, ComboBoxBounds)
If e.Index >= 0 Then
If Not IsCellEmpty(ClaimCodes(e.Index)("code")) Then
e.Graphics.DrawString(ClaimCodes(e.Index)("code").ToString, ComboBoxFont, TextBrush, New RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height))
End If
End If
End Sub
2条答案
按热度按时间rbpvctlc1#
感谢@LarsTech和@Jimi的评论,帮助我找到了问题所在。当我在测试时,我也注意到选择并没有完全按照预期工作(* 我以前没有注意到这一点 ),所以他们的评论把我指向了一个完全不同的方向。这基本上是一个“粗略的草案”的解决方案,我扔在一起,让它工作。看看我的另一个被接受的答案,即代码的“清理”版本,它包含了来自评论的建议。
正如问题中提到的,我已经为这些
ComboBox
事件定制了一个DrawItem
事件处理程序。该事件处理程序引用了“原始的”未排序的DataTable
,以添加一些UX“美化”,以便用户能够更容易地识别何时选择ComboBox
( 如果没有它,用户很难看到何时框处于焦点 *)。为了解决这个问题,我将
ComboBox
es使用的DataTable
s移动到类级别,而不是在方法中:(* 是的,我重新使用了之前的
ClaimCodes
对象名称 *)然后我修改了我的
LoadCodeComboBoxes()
方法来填充那些类级别的DataTable
对象,而不是方法本地对象:最后,我更新了我的
DrawItem
事件处理程序,以使用单个类级别的DataTable
s:现在每个都使用自己的排序
DataTable
,一切似乎都按预期工作。aiqt4smr2#
“最终”修改代码,以从原始评论中删除建议
现在我能够找到意外行为的原因,我已经回去做了一些代码清理,以纳入@Jimi提出的建议。我已经完全删除了类级别的
DataTable
对象,并摆脱了LoadCodeComboBoxes()
方法中的所有DefaultView
“混乱”(* 注:**我已经完全限定了大多数对象类型,只是为了绝对清晰起见。您可以根据需要删除“无关的”名称空间。*):此外,通过消除类级别的
DataTable
s并采纳使用事件参数属性的建议,我能够创建一个更“通用”的事件处理程序,可以将其分配给任何ComboBox
:SolidBrush
对象的Using
语句,以便在方法中正确处理它们。*有了这些,我删除了所有单独的表单内事件处理程序(
cboClaimCode_DrawItem
等),并将它们分配到一个应用其他事件处理程序的方法中:我希望这能帮助任何人寻找如何填充他们的
ComboBox
es。再次感谢@Jimi和@LarsTech的帮助和建议。