任何方式,每行2值的组合框? [英] Any way for a combo box with 2 values per line?

查看:141
本文介绍了任何方式,每行2值的组合框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在寻找与我可以与一起使用组合框的功能选项
列表视图。

I'm looking for an option with which I can use the functionality of a combobox together with a listview.

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

The reason for this is because I have SQL queries which can't have more than 1 output, which I can get in some cases.

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

E.g. my SQL table looks somewhat like this

UNIQUE_ID - 产品名称搜索
 123456789 - 西蒙结果
 987654321 - 西蒙

基本上相同的名称,可在数据库中的多个次,用它自己的ID的每个条目。

Basically the same name can be in the database multiple times, each entry with it's own ID.

有关用户的缘故,我不能让他们选择什么记录基于ID进行编辑,而不是我让他们立足于名称所选择的记录。当有超过1记录从我的查询结果,虽然,我得到一个MySQL例外。

For the user's sake, I can't have them choose what records to edit based on the ID, instead I have them base the chosen record on the name. When there's more than 1 record resulting from my query though, I get a MySQL exception.

下面是有问题的MySQL查询:结果
选择幸存者世界空间在哪里is_dead ='0'_和survivor.unique_id =(从配置文件选择UNIQUE_ID其中name ='&放靶标放,')

Here's the MySQL query in question:
"SELECT worldspace from survivor where is_dead = '0' _ and survivor.unique_id = (select unique_id from profile where name = '" & target & "')"

从查询的输出,然后在另一个更新使用查询。

The output from that query is then used in another UPDATE query.

所以,有可能是我的组合框有两个ID&放大器;名称作为值,它们之间有明确分工所以整个值保持良好的可读性,因为它会在列表视图元素吗?

So, is it possible for my combobox to have both the ID & the name as values, with a clear seperation between them so the entire value stays well readable, as it would do in a listview element?

推荐答案

我看你已经得到了HighCore治疗如何轻松一切都在WPF和多少的WinForms很烂。但是,你可能有兴趣知道,你可以在的WinForms做到这一点,太。你只是做了一点点不同。它应是毫不奇怪的标准设计成语WinForms和WPF不同;这并不能证明一个是比其他更好,它只是意味着你需要学习如何使用您正在使用的之一。 (虽然,不可否认,一些票友东西是比较困难的使用被发明了20年前与Windows本身的UI框架来实现。电源它的确实的已经是相当了不起的。)

I see you've already gotten the HighCore treatment about how easy everything is in WPF and how much WinForms sucks. But you might be interested to know that you can do this in WinForms, too. You just do it a little bit differently. It should come as no surprise that the standard design idioms differ in WinForms and WPF; that doesn't justify one being "better" than the other, it just means you need to learn how to use the one you're using. (Although, admittedly, some of the fancier stuff is a bit more difficult to achieve using a UI framework that was invented 20 years ago with Windows itself. The power it does have is rather remarkable.)

有格式化的信息的两种基本方式:一切都在一行(我认为是你的问题问)或信息在两行的作品,其中每个项目基本上是一个两行单元(这就是HighCore的WPF解决方案演示)。

There are two basic ways of formatting the information: everything on a single line (which I believe is what you asked for in the question) or the pieces of information on two lines where each item is basically a two-line unit (which is what HighCore's WPF solution demonstrates).

我们来看看把一切在一行首先,这真的很简单。你不需要为分离柱,你可以用某种独特的分隔符,当您添加的项目组合框,如垂直管道( | )或破折号( - )。就像你在问题中使用

We'll look at putting everything on a single line first, which really is simple. You don't need columns for separation, you can just use some kind of distinctive separator character when you add the items to the combobox, such as a vertical pipe (|) or a dash (-) like you used in the question.

这工作这么好,因为 ComboBox.Items.Add 方法接受类型的参数对象,其上它只是调用的ToString 来得到控件中显示的值。如果你传递一个字符串,它会显示该字符串。

This works so well because the ComboBox.Items.Add method accepts a parameter of type Object, on which it just calls ToString to get the value displayed in the control. If you pass it a string, it displays that string.

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()

          &NBSP ;    或NBSP;              

                OR                

您甚至可以通过自定义类到跟踪的唯一ID和名称属性(和其他任何你想要的)的添加方法和覆盖的ToString 用于显示的方法。

You can even pass a custom class to the Add method that keeps track of the unique ID and name properties (and anything else you want) and overrides the ToString method for display purposes.

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()

杀青锯齿

当然,如果在每一组中的第一项可以是可变长度的和您使用的是可变宽度字体(即一个不一样等宽的星球做除了code编辑每个UI)分离器将不排队,你不会得到两个很好的格式列。相反,它看起来一切混乱和丑陋的。

Fixing the Jaggies

Granted, if the first item in each set can be of variable length and you're using a variable-width font (i.e., one that is not monospaced like every UI on the planet does except code editors), the separators won't line up and you won't get two nicely-formatted columns. Instead, it looks all jumbled and ugly.

这将是很好,将自动处理所有排队为我们ComboBox控件支持制表符,可惜事实并非如此。这是令人遗憾的是,基础Win32控制有严格限制。

It would be nice of the ComboBox control supported tab characters that would handle lining everything up for us automatically, but unfortunately it does not. This is, regrettably, a hard limitation of the underlying Win32 control.

修复这个衣衫褴褛的边缘问题是可能的,但它确实变得有点复杂。它需要采取在下拉列表中的项目,被称为所有者绘制。

Fixing this ragged-edge problem is possible, but it does get a bit complicated. It requires taking over the drawing of the items in the combobox, referred to as "owner-draw".

要做到这一点,你的 DrawMode 属性设置为 OwnerDrawFixed 并办理<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.drawitem.aspx\"><$c$c>DrawItem事件手动绘制文本。您可以使用<$c$c>TextRenderer.DrawText方法来绘制标题字符串 <子>(因为这符合什么的WinForms内部使用;避免使用 Graphics.DrawString 和<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.forms.textrenderer.measuretext.aspx\"><$c$c>TextRenderer.MeasureText如果需要的话,以获得间距权利。绘图code可以(也应该)使用所有由 DrawItemEventArgs 通过Ë提供的默认属性 。你不需要 OwnerDrawVariable 模式或处理 MeasureItem 事件,因为宽度和高度的每个项目中不能变化的这种情况下。

To do this, you set its DrawMode property to OwnerDrawFixed and handle the DrawItem event to manually draw the text. You'll use the TextRenderer.DrawText method to draw the caption string (because that matches what WinForms uses internally; avoid using Graphics.DrawString), and TextRenderer.MeasureText if necessary to get the spacing right. The drawing code can (and should) use all of the default properties provided by the DrawItemEventArgs passed as e. You don't need OwnerDrawVariable mode or to handle the MeasureItem event because the width and height of each item cannot vary in this case.

只是为了给你一个想法,这里有一个快速和肮脏的实现,只是把一半的下拉垂直:

Just to give you an idea, here's a quick-and-dirty implementation that simply divides the drop-down in half vertically:

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

现在,该是寻找pretty不错。你当然可以改善由 DRAWITEM 事件处理方法所使用的技术,但它的作品了pretty还有就是,只要组合框做了正确的尺寸对于值将被显示。

Now, this is looking pretty good. You can certainly improve on the technique used by the DrawItem event handler method, but it works out pretty well as is, so long as the combobox is made the right size for the values it will be displaying.

第二个方法,其中每个项目是一个两线组像HighCore的WPF例如,最好是通过继承内置ComboBox控件,并采取完全控制其绘图程序完成。但是,这没有什么可害怕的,继承的控制是一个标准的WinForms成语来获得对UI额外的控制。 (你可以,当然,实现这一切通过处理事件,如我上面做了,但是我觉得子类是一种更清洁的方式,也促进了重用,如果你想拥有多个组合框,所有以类似的方式行事。)

The second method, where each item is a two-line group like HighCore's WPF example, is best done by subclassing the built-in ComboBox control and taking complete control its drawing routines. But that's nothing to be afraid of, subclassing a control is a standard WinForms idiom to gain extra control over the UI. (You could, of course, implement all of this by handling events like I did above, but I think subclassing is a much cleaner approach and also promotes reuse if you want to have multiple comboboxes that all behave in a similar fashion.)

同样,你不需要 OwnerDrawVariable ,因为项目的高度是不会改变的。你永远有两条线路,所以一个固定的高度工作正常。你只需要确保您设置的<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.itemheight.aspx\"><$c$c>ItemHeight财产,因为你将有两条线路翻一番正常值。你可以使用 TextRenderer.MeasureText 这个做复杂的方式,还是我选择了后者本演示中,你可以做到这一点,只需用2乘以默认值的简单方法。

Again, you don't need OwnerDrawVariable because the height of the items is not going to change. You'll always have two lines, so a fixed height works fine. You just need to make sure that you set the ItemHeight property to double of its normal value because you're going to have two lines. You could do this the complicated way using TextRenderer.MeasureText, or you could do it the easy way by just multiplying the default value by 2. I chose the latter for this demo.

添加这个类到你的项目,然后用 MultiLineComboBox 控制,而不是内置的 System.Windows.Forms.ComboBox 。所有的属性和方法的工作相同。

Add this class into your project, and then use the MultiLineComboBoxcontrol instead of the built-in System.Windows.Forms.ComboBox. All of the properties and methods work the same.

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

我们现在已经有了不坏,而是慷慨地在绘图code多一点努力在的OnDrawItem ,我们可以添加一些额外的视觉幻想一夜暴富和

What we've got now isn't bad, but by lavishing a bit more effort on the drawing code in OnDrawItem, we can add some extra visual fancies and flourishes.

例如,如果没有选择矩形,这将是pretty很难说,这些实际上是两线单位。这是不寻常的组合框控件,所以对于可用性的原因您的应用程序应该走出去的方式,使这个昭然若揭。我们可以做到这一点的方法之一是缩进第二行。你会记得,我说的是内置​​的ComboBox控件不支持标签?嗯,这已经不适用,因为我们现在做绘图自己。我们可以通过加入一些额外的填充到第二行的开始仿效标签

For example, without the selection rectangle, it would be pretty hard to tell that these are actually two-line units. That's unusual for a combobox control, so for usability reasons your application should go out of its way to make this abundantly clear. One way we might do that is by indenting the second line. You'll recall that I said that the built-in combobox control doesn't support tabs? Well that doesn't apply anymore, since we're doing the drawing ourselves now. We can emulate tabs by adding some extra padding to the beginning of the second line.

如果你想要的标签(ID和名称)从实际值分开设置,你可以做到这一点,太。也许你会做标签大胆减仓的文本颜色。

If you wanted the labels ("ID:" and "Name:") to be set apart from the actual values, you could do that, too. Perhaps you'd make the labels bold and lighten the text color.

所以你看到仅仅通过与绘图code打,你可以创建几乎任何你想要的效果。我们有完全的控制,并通过在可所有的地方重用的 MultiLineComboBox 类包装这一切,你的code的其余部分甚至没有要知道,有什么特别的事情。酷吧?

So you see that just by playing with the drawing code, you can create almost any effect you want. We have complete control, and by wrapping it all up in a MultiLineComboBox class that can be reused all over the place, the rest of your code doesn't even have to know that anything special is happening. Cool, right?

最后,我将是失职,如果我不指出,你可以跳过做这一切工作,的采取的各种各样的已经编写自定义多线组合框控件你挑

And finally, I would be remiss if I didn't point out that you could skip doing all of this work and take your pick of the variety of custom multi-line combobox controls that have already been written.

这其中是pretty漂亮。它实际上只是显示当您单击组合框的下拉箭头ListView控件。这样做,你会得到一切都是免费的ListView控件的格式细微的,但它的行为就像一个普通的ComboBox。

This one is pretty nifty. It actually just displays a ListView control when you click the drop-down arrow on the combobox. In doing so, you get all of the formatting niceties of the ListView control for free, but it behaves just like a regular ComboBox.

这篇关于任何方式,每行2值的组合框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆