【问题标题】:Refining a custom listbox control优化自定义列表框控件
【发布时间】:2013-10-12 00:52:35
【问题描述】:

我制作了一种自定义列表框,并包含了为每个项目添加图像的功能。 我希望能够随意更改这些图像,并且不太确定如何去做。目前您只能在每件商品中选择您想要的图片。

Public Class CustomListBox
Public label As Label
Public pic As PictureBox
Public panel As Panel
Public itemID As String
Public itemCollection As New Collection
Public bgColor As Color
Public txtEnterColor As Color = Color.FromArgb(80, 80, 80)
Public txtColor As Color = Color.FromArgb(150, 150, 150)
Public bgEntercolor As Color = Color.FromArgb(230, 230, 230)
Public x, y, paddingInt As Integer
Public itemHeight As Integer = 40
Public image As Image = My.Resources.FavNone
Public Event Item_Clicked()

Private Property ItemBackColor As Color
    Get
        Return BackColor
    End Get
    Set(ByVal value As Color)
        bgColor = value
    End Set
End Property

Private Property ItemPadding As Padding
    Get
        Return Padding
    End Get
    Set(ByVal value As Padding)
        Padding = value
    End Set
End Property

Public Property HoverBackColor As Color
    Get
        Return bgEntercolor
    End Get
    Set(ByVal value As Color)
        bgEntercolor = value
    End Set
End Property

Public Property ItemImage As Image
    Get
        Return image
    End Get
    Set(ByVal value As Image)
        image = value
    End Set
End Property

Public Property HoverTextColor As Color
    Get
        Return txtEnterColor
    End Get
    Set(ByVal value As Color)
        txtEnterColor = value
    End Set
End Property

Public Property TextColor As Color
    Get
        Return txtColor
    End Get
    Set(ByVal value As Color)
        txtColor = value
    End Set
End Property

Public Property TrueItemHeight As Integer
    Get
        Return itemHeight
    End Get
    Set(ByVal value As Integer)
        itemHeight = value
    End Set
End Property

Public Sub UpdateItems()
    For Each item As String In itemCollection
        label = New Label
        pic = New PictureBox
        panel = New Panel
        With pic
            .Width = itemHeight
            .Height = itemHeight
            .SizeMode = PictureBoxSizeMode.Zoom
            .Image = image
        End With
        With label
            .BackColor = (bgColor)
            .ForeColor = (txtColor)
            .Width = Me.Width - itemHeight
            .Height = itemHeight
            .Tag = item
            .Height = itemHeight
            .Padding = ItemPadding
            .Text = item
            .Left = itemHeight
            .TextAlign = ContentAlignment.MiddleLeft
            AddHandler label.MouseEnter, AddressOf Item_Enter
            AddHandler label.MouseLeave, AddressOf Item_Leave
            AddHandler label.MouseUp, AddressOf Item_Mousedown
        End With
        With panel
            .Location = New Point(x, y)
            .Width = Me.Width
            .Height = itemHeight
            .Controls.Add(pic)
            .Controls.Add(label)
            y += .Height + paddingInt
        End With
        Me.Controls.Add(panel)
    Next
End Sub

Private Sub Item_Enter(ByVal sender As Label, ByVal e As EventArgs)
    sender.BackColor = (bgEnterColor)
    sender.ForeColor = (txtEnterColor)
    itemID = sender.Tag
End Sub

Private Sub Item_Leave(ByVal sender As Label, ByVal e As EventArgs)
    sender.BackColor = (bgColor)
    sender.ForeColor = (txtColor)
End Sub

Private Sub Item_Mousedown(ByVal sender As Label, ByVal e As MouseEventArgs)
    Select Case e.button
        Case Windows.Forms.MouseButtons.Left
            RaiseEvent Item_Clicked()
    End Select
End Sub

End Class

我知道我需要在项目的点击事件中添加一些东西。可以用标签的索引号设置一个变量,也许......?

另外,我如何在输入代码时获得自动建议。例如,我希望能够输入 CustomListBox1.itemCollection.add("Text", imageSrc)...等我只是不知道要在 Google 中输入什么,除了查看大量自定义控件,直到找到一个包含这个。

编辑

我查看了this 自定义列表框。

我尝试为每个项目添加一个 MouseMove 事件,因此认为它就像放置这个一样简单:

Private Sub HoverItem(ByVal item As ColorListboxItem, ByVal e As MouseEventArgs)
    msgbox(1)
End Sub

...在“方法”区域,然后

 AddHandler .mousemove, AddressOf HoverItem

到“OnDrawItem”子。对我来说不幸的是,这显然不像没有 msgbox 显示的那么容易。 任何对此控件有经验的人都可以就其工作原理提供一些见解。也许是 MouseMove 事件的一个例子,所以我会了解如何添加更多事件(Mouseleave、DblClick...等)

【问题讨论】:

  • 这就是 WPF 的用途。无需重新发明轮子,绑定已经到位。

标签: vb.net visual-studio listbox custom-controls listboxitems


【解决方案1】:

@JoshMason 所说的大部分内容是正确的,但如果您坚持这样做,那么您不仅需要为您的项目提供索引的集合/数组,还需要一个链接的关联集合/数组以用于相应的图像。

这样您就可以访问项目/图像的索引(当然要适当地公开),这样您就可以像为项目(索引)分配文本一样为其分配图像,并且您需要确保您删除项目的代码帐户也会删除相应的图像,但如果您正确链接它们,这应该会自动发生。

编辑:为了获得灵感,请快速查看this

【讨论】:

  • 我现在在点击时设置了一个变量,让它只对点击的第一个项目起作用。我想不出如何解决这个问题,以便每次点击都会声明一个新的 picbox Dim img As new PictureBox = Me.SelectedItem.Controls.Item(0)
  • 不不,你不能那样做。最好的方法是创建一个类文件并引用它,这种编码非常不优雅和缓慢。
  • 我不明白你的意思。或许可以举个例子。 (我会创建一个新类,对吧?)
  • 我想你可能需要那个,所以我发布了一个编辑,检查一下。
  • 我之前遇到过这个例子,但并不完全理解哪个部分适用于我在这里尝试做的事情。这就是我产生自己的想法的地方,因为我没有完全理解代码,因此更难编辑
【解决方案2】:

这看起来很熟悉 - 我有一些与房子和跟踪一堆缩略图非常相似的东西。一些东西。它的编写方式更像是一个 ListBox 助手而不是自定义控件。这没有什么问题,但是如果您希望它显示在工具箱中并且更可重用,请考虑对其进行改造:

Public Class CustomListBox
    Inherits Panel           ' or maybe Component, depending....

按照您的编写方式,您试图通过维护标签、图片框和面板的集合来模拟 ListBox 的功能。如果您开始将每个面板+图片框+文本框视为其自身的整体事物(控件),您可以在该级别内化一些功能(例如事件处理),并将 ListBox 帮助器主要用于管理与用户的交互或应用程序(或离开)。我认为自动建议在成为实际控件或组件之前不会起作用。

 Private WithEvents mLbl As TextBox   ' just recently decided to allow text edits
 Private WithEvents mPic As PictureBox

 Public Sub New(ByVal uniqueName As String)
    mLbl = New TextBox
    mPic = New PictureBox

    Name = uniqueName
    .... set required lbl/txt properties

    MyBase.Controls.Add(mLbl)   ' we inherit from Panel
    .... set pic controls    
    MyBase.Controls.Add(mPic)
    ...
    ...

   ' no need for AddHandler, each Item comes with its own built in event
   Private Sub mPic_DClick(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles mPic.DoubleClick, mLbl.DoubleClick

     IsSelected = Not _IsSelected

   End Sub

在使用默认或基本道具创建后,创建它的类在将其添加到滚动面板之前在滚动面板上设置独特的属性,如文本、图像和位置:

   frmMain.pnlImgList.Controls.Add(newImgItem)

IsSelected(上图)是一个属性,当它从 False 变为 True 时,我会引发一个新事件 ItemSelected 来通知包含每个“ImgItem”控件的应用程序/面板。该应用程序不需要知道是文本框还是点击了图片,因为 ImgItem 将处理它(如编辑文本)。在您的情况下,这可能会在选择/聚焦等时改变颜色。(将其分解为两部分最终会让您摆脱创建所有新项目的大过程)。

我没有这些的任何内部集合。它们被添加到表单上的面板中,并且该面板的控件集合用于此目的。当这些东西中的一个新添加到表单中时,它必须使用 AddHandler 连接到事件以处理像 ItemSelected 之类的事件(有一个 ControlAdded/ControlRemoved 事件,它是一个很好的地方将这些挂钩/取消挂钩到 Selected事件处理程序!)

您可以使用外观和行为类似于列表框的项目滚动面板来执行类似操作。

在您执行更改图片等操作之前,您需要一个唯一标识符,以便知道要更改哪张图片。看起来您使用文本作为名称。根据您使用它的方式,这可能会起作用,但如果用户可以编辑文本,他们可以创建一个副本;如果名称更改,您将面临丢失跟踪的风险。因此,请考虑使用您自己不向用户公开的唯一名称标记它们:

' this would be passed to Sub New when creating a new Item
newName = System.Guid.NewGuid.ToString()

唯一 ID(名称)是 ItemSelected 事件中的事件 args 的一部分,便于在表单上找到每个控件:

 ThisCtl = pnlItems.Controls(sender.Name)

要更改图像,只需在“项目”级别公开它:

 Friend Property Pic() As Bitmap
    Get
        ' I dont recall why this is this way, maybe an artifact
        ' from trying different things.
        Return CType(mPic.BackgroundImage, Bitmap)
    End Get

然后表单或您的助手可以更改图像:

 ThisCtl = pnlItems.Controls(sender.Name)      
 ThisCtl.Pic = newImage

frmName.pnlItems(sender.Name).Pic = newImage

重新编辑:您想用鼠标执行的某些操作(更改颜色)可能可以通过更改鼠标事件中的 BackColor 以便宜的方式完成。但是,通过将其设置为适当的组件可能会更好地处理某些事情,以便您可以根据需要阴影和覆盖鼠标和绘制程序。如果您将项目保存在实际的 ListBOx 中,则几乎可以肯定您将不得不挂钩到 DrawItem 绘制事件。在您决定是否将其转换为组件之后再担心。

HTH

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2011-02-28
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多