gpt4 book ai didi

vb.net - 每行有2个值的组合框有什么办法吗?

转载 作者:行者123 更新时间:2023-12-04 08:18:13 24 4
gpt4 key购买 nike

我正在寻找一个可以与组合框一起使用组合框功能的选项
列表显示。

这样做的原因是因为我有不能超过1个输出的SQL查询,在某些情况下可以得到。

例如。我的SQL表看起来像这样

Unique_ID - Name

123456789 - Simon

987654321 - Simon


基本上,同一名称可以多次出现在数据库中,每个条目都有自己的ID。

为了用户的缘故,我不能让他们根据ID选择要编辑的记录,而是让他们将所选记录基于名称。当查询产生的记录多于1条时,我得到一个MySQL异常。

这是有问题的MySQL查询:
"SELECT worldspace from survivor where is_dead = '0' _ and survivor.unique_id = (select unique_id from profile where name = '" & target & "')"

然后,该查询的输出将在另一个UPDATE查询中使用。

因此,对于我的组合框来说,是否有可能同时具有ID和名称作为值,并且它们之间有明显的分隔,从而使整个值保持良好的可读性,就像在listview元素中所做的那样?

最佳答案

我看到您已经对HighCore进行了处理,以了解WPF中所有内容的简易程度以及WinForms的消耗量。但是您可能想知道您也可以在WinForms中执行此操作。您只是做了一些不同的事情。毫无疑问,WinForms和WPF中的标准设计习惯有所不同。这并不能证明一个人比另一个人“更好”,这只是意味着您需要学习如何使用正在使用的那个人。 (尽管,诚然,使用20年前与Windows一起发明的UI框架,要实现一些更高级的东西要困难一些。它确实具有相当强大的功能。)

格式化信息的基本方法有两种:单行中的所有内容(我相信这是您在问题中所要的内容)或两行中的信息片段,其中每一项基本上都是两行单位(即HighCore的WPF解决方案演示)。

单行格式

简化方法

我们将首先将所有内容放在一行上,这确实很简单。您不需要分隔的列,将项目添加到组合框时,只需使用某种独特的分隔符即可,例如您使用的竖管(|)或破折号(-)问题。

这很好用,因为ComboBox.Items.Add方法接受类型为Object的参数,该方法只调用ToString即可获取控件中显示的值。如果您传递一个字符串,它将显示该字符串。

myComboBox.BeginUpdate()
For Each record In myRecordSet
myComboBox.Items.Add(String.Format("{0} | {1}", record.UniqueID, record.Name))
' or even...
myComboBox.Items.Add(String.Format("{0} ({1})", record.UniqueID, record.Name))
Next record
myComboBox.EndUpdate()


要么

通过OOP进行的增量改进

您甚至可以将自定义类传递给 Add方法,以跟踪唯一的ID和名称属性(以及您想要的任何其他内容),并覆盖 ToString方法以进行显示。

Public Class Record
Public Property UniqueID As Long ' maybe this should be a string too
Public Property Name As String

Public Overrides Function ToString() As String
' Generate the string that will be displayed in the combobox for this
' record, just like we did above when adding it directly to the combobox,
' except that in this case, it will be dynamically generated on the fly,
' allowing you to also track state information along with each item.
Return String.Format("{0} | {1}", Me.UniqueID, Me.Name)
End Function
End Class

' ...

' (somewhere else, when you add the items to the combobox:)
myComboBox.BeginUpdate()
For Each r In myRecordSet
' Create a Record object representing this item, and set its properties.
Dim newRecord As New Record
newRecord.UniqueID = r.UniqueID
newRecord.Name = r.Name
' ...etc.

' Then, add that object to the combobox.
myComboBox.Items.Add(newRecord)
Next r
myComboBox.EndUpdate()


修复锯齿

当然,如果每组中的第一项可以是可变长度的,并且您使用的是可变宽度的字体(即,除了代码编辑器之外,不是像星球上的每个UI那样均等间距的字体),分隔符都不会起来,您将不会得到两个格式良好的列。取而代之的是,看起来一切混乱而丑陋。



最好使用ComboBox控件支持的制表符,它们可以自动为我们整理所有内容,但不幸的是事实并非如此。遗憾的是,这是基础Win32控件的硬限制。

解决这个参差不齐的问题是可能的,但是确实有些复杂。它需要接管组合框中的项目图纸,称为“所有者图纸”。

为此,将其 DrawMode属性设置为 OwnerDrawFixed并处理 DrawItem事件以手动绘制文本。您将使用 TextRenderer.DrawText方法绘制标题字符串(因为 that matches what WinForms uses internally;避免使用 Graphics.DrawString),并在必要时使用 TextRenderer.MeasureText来获得正确的间距。绘图代码可以(并且应该)使用作为 DrawItemEventArgs传递的 e提供的所有默认属性。您不需要 OwnerDrawVariable模式或处理 MeasureItem事件,因为在这种情况下,每个项目的宽度和高度都不能改变。

只是为了给您一个主意,这是一个快速实用的实现,它仅将下拉菜单垂直分割为两半:

Private Sub myComboBox_DrawItem(sender As Object, e As DrawItemEventArgs) Handles myComboBox.DrawItem
' Fill the background.
e.DrawBackground()

' Extract the Record object corresponding to the combobox item to be drawn.
Dim record As Record = DirectCast(myComboBox.Items(e.Index), Record)
Dim id As String = record.UniqueID.ToString()
Dim name As String = record.Name

' Calculate important positions based on the area of the drop-down box.
Dim xLeft As Integer = e.Bounds.Location.X
Dim xRight As Integer = xLeft + e.Bounds.Width
Dim xMid As Integer = (xRight - xLeft) / 2
Dim yTop As Integer = e.Bounds.Location.Y
Dim yBottom As Integer = yTop + e.Bounds.Height

' Draw the first (Unique ID) string in the first half.
TextRenderer.DrawText(e.Graphics, id, e.Font, New Point(xLeft, yTop), e.ForeColor)

' Draw the column separator line right down the middle.
e.Graphics.DrawLine(SystemPens.ButtonFace, xMid, yTop, xMid, yBottom)

' Draw the second (Name) string in the second half, adding a bit of padding.
TextRenderer.DrawText(e.Graphics, name, e.Font, New Point(xMid + 5, yTop), e.ForeColor, TextFormatFlags.Left)

' Finally, draw the focus rectangle.
e.DrawFocusRectangle()
End Sub




现在,这看起来还不错。您当然可以改进 DrawItem事件处理程序方法所使用的技术,但是只要组合框的大小适合将要显示的值,它就可以很好地工作。

多行格式

定义自定义ComboBox类

第二种方法最好是将内置ComboBox控件子类化,并完全控制其绘制例程,从而将每个项目都像HighCore的WPF示例那样由两行组成。但这没什么好担心的,将控件子类化是一种标准的WinForms习惯用法,以获得对UI的额外控制。 (当然,您可以通过像上面一样处理事件来实现所有这些功能,但是我认为子类化是一种更为简洁的方法,并且如果您希望拥有多个以相似方式工作的组合框,那么它也可以促进重用。)

同样,您不需要 OwnerDrawVariable,因为项目的高度不会改变。您将始终有两行,因此固定高度可以正常工作。您只需要确保将 ItemHeight属性设置为其正常值的两倍,因为您将有两行内容。您可以使用 TextRenderer.MeasureText进行复杂的操作,也可以通过将默认值乘以2来实现简单的操作。我在本演示中选择了后者。

将此类添加到您的项目,然后使用 MultiLineComboBox控件而不是内置的 System.Windows.Forms.ComboBox。所有的属性和方法都相同。

Public Class MultiLineComboBox : Inherits ComboBox
Public Sub New()
' Call the base class.
MyBase.New()

' Typing a value into this combobox won't make sense, so make it impossible.
Me.DropDownStyle = ComboBoxStyle.DropDownList

' Set the height of each item to be twice its normal value
' (because we have two lines instead of one).
Me.ItemHeight *= 2
End Sub

Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
' Call the base class.
MyBase.OnDrawItem(e)

' Fill the background.
e.DrawBackground()

' Extract the Record object corresponding to the combobox item to be drawn.
If (e.Index >= 0) Then
Dim record As Record = DirectCast(Me.Items(e.Index), Record)

' Format the item's caption string.
Dim caption As String = String.Format("ID: {0}{1}Name: {2}", record.UniqueID.ToString(), Environment.NewLine, record.Name)

' And then draw that string, left-aligned and vertically centered.
TextRenderer.DrawText(e.Graphics, caption, e.Font, e.Bounds, e.ForeColor, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)
End If

' Finally, draw the focus rectangle.
e.DrawFocusRectangle()
End Sub
End Class




添加幻想和繁荣

现在的功能还不错,但是通过在 OnDrawItem中的绘图代码上花费更多的精力,我们可以添加一些额外的视觉效果和繁荣。

例如,如果没有选择矩形,很难说出它们实际上是两行单位。对于组合框控件而言,这是不寻常的,因此出于可用性的考虑,您的应用程序应尽力使其清晰可见。我们可以这样做的一种方法是缩进第二行。您还记得我说过的内置组合框控件不支持选项卡吗?嗯,这不再适用了,因为我们现在正在自己绘制图纸。我们可以通过在第二行的开头添加一些额外的填充来模拟选项卡。

如果希望将标签(“ ID:”和“名称:”)与实际值分开设置,也可以这样做。也许您可以将标签设为粗体并使文本颜色变浅。

因此,您看到只需使用绘图代码,就可以创建几乎任何想要的效果。我们拥有完全的控制权,并将其包装在可以在所有地方重复使用的 MultiLineComboBox类中,您的其余代码甚至不必知道发生了什么特别的事情。酷吧?

避免所有工作

最后,如果我没有指出您可以跳过所有这些工作以及已经编写的各种自定义多行组合框控件的 take your pick,我将不知所措。

This one非常漂亮。当您单击组合框上的下拉箭头时,它实际上仅显示一个ListView控件。这样,您可以免费获得ListView控件的所有格式化功能,但是其行为就像常规的ComboBox一样。

关于vb.net - 每行有2个值的组合框有什么办法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15514698/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com