[英]VB.NET - Customizing Listview/Listbox
So there are a few Answered questions but I still dont really understand what i'm meant to do. 所以有一些已回答的问题,但我仍然不明白我的意思。 Like how can I basically make my Listview very customized.
就像我怎么能基本上使我的Listview非常自定义。
What im trying to get it to look like is: 我试图让它看起来像是:
As you can see it's HEAVILLY customized - I made this in Photoshop if you were wondering and I dont EXACTLY need the Scrollbar customized or that Hover-Highlight effect as of right now but in the Future a way to do it would be needed. 正如你所看到的那样HEAVILLY定制 - 如果你想知道我在Photoshop中做了这个,我现在不需要自定义Scrollbar或Hover-Highlight效果,但是在未来我需要一种方法来做到这一点。
Any ideas how I can achieve this? 我有什么想法可以达到这个目的吗?
EDIT: The closest thing I can get it to is: 编辑:我能得到的最接近的是:
But theres a "FEW" issues - I cant get the Text alignment/position to look right as I need to put 2 spaces before the Text for it to actually look decent which "MIGHT" give issues for me in the future when trying to get actions on click.
但是有一个“FEW”问题 - 我不能让文本对齐/位置看起来正确,因为我需要在文本之前放置2个空格以使其实际上看起来不错,“MIGHT”在将来尝试获取时会给我带来问题点击动作。 Next, There's for some reason no option to using Borders/Grids which remove the ability to do that slightly darker gray border around the Boxes in the first image.
接下来,由于某种原因,没有选择使用边框/网格,这样就无法在第一张图像中删除在Boxes周围稍微变暗的灰色边框。 Any ideas guys?
有什么想法吗?
(What I used to make it like this is: http://www.vbforums.com/showthread.php?599375-ListBox-with-custom-items-(colors-images-text-alignment) ) (我曾经这样做的是: http : //www.vbforums.com/showthread.php?599375-ListBox-with-custom-items-(colors-images-text-alignment) )
Edit 2: Re-Edit: Ok I tought I got the Highlight Color sorted but it doesnt seem like it as im using FillRectangle but no matter how I put the Bounds (Which are correct) it seems to leave an extra like 1px border of White for about 1-2 seconds before its refreshed and gone. 编辑2:重新编辑:好吧我想我得到了突出显示颜色排序,但它似乎不像我使用FillRectangle,但无论我如何把边界(这是正确的)它似乎留下额外像1px边框的白色在刷新之前大约1-2秒消失。 Anyway to fix this?
有任何解决这个问题的方法吗?
Edit 3: The http://www.vbforums.com/showthread.php?599375-ListBox-with-custom-items-(colors-images-text-alignment) ListBox I was using where I "ALMOST" got it done wont work for me due to it just not being stable - If I edit anything after making the ColorListBox in the Design mode it will just not work and give me errors which is annoying. 编辑3: http ://www.vbforums.com/showthread.php?599375-ListBox-with-custom-items-(colors-images-text-alignment ) ListBox我正在使用的地方我“ALMOST”完成它不会因为它不稳定而为我工作 - 如果我在设计模式下制作ColorListBox之后编辑任何东西它将无法正常工作并给我带来令人讨厌的错误。 It also has the "SelectedItem" parameter as no longer an Object which ruins half of my code.
它还有“SelectedItem”参数,因为它不再是一个破坏我代码一半的Object。 Other then that if those 2 are fixable I guess it would work but I have no idea how to fix it :(
除此之外,如果那些2是可修复的,我想它会起作用,但我不知道如何解决它:(
So I reverted to a VERY basic ListBox for now with just text until you guys can help find a way to customize it like the first image above. 所以我现在只用文本恢复到非常基本的ListBox,直到你们可以帮助找到一种方法来定制它,就像上面的第一张图片一样。
It is not at all clear what you want exactly. 完全不清楚你想要什么。
Like how can I basically make my Listview very customized
is vague and very broad (and why you didn't get an answer you liked). Like how can I basically make my Listview very customized
是模糊和非常广泛的(为什么你没有得到你喜欢的答案)。
A picture is nice, but words describing the desired appearance would have been better. 画面很好,但描述所需外观的单词会更好。 Given a picture to scrutinize, there is no way to know what is Important and what is just there...because.
鉴于要仔细检查的图片,没有办法知道什么是重要的,什么是正确的......因为。 I assume every detail is important based on
very customized
. 我假设每个细节都非常重要,基于
very customized
。 Additionally: 另外:
Listview/Listbox
Pick one: they are very different controls. Listview/Listbox
选择一个:它们是非常不同的控件。 ListView
, so I scratched the LV 1 . ListView
来说是非常有问题的,所以我抓了LV 1 。 ListBox
/ ListView
items do not normally light up when the mouse passes over (the LV can when HotTracking
is true, but thats only when the mouse is over the Item
not subitem(s)). ListBox
/ ListView
项目通常不亮(当HotTracking
为真时,LV可以HotTracking
,但只有当鼠标在Item
而不是子项目时HotTracking
)。 HotLight
and Selected
coloring is usually handled by the OS (==Operating System) respecting the theme and color choices of the user. HotLight
和Selected
着色通常由操作系统(==操作系统)处理,尊重用户的主题和颜色选择。 Is this gadget supposed to ignore those, or is your theme using some shade of gray for Highlight ? I measured the elements in the first image carefully to get some metrics, then made guesses on the answers to the above. 我仔细测量了第一张图片中的元素以获得一些指标,然后猜测了上面的答案。
Use a Button. 使用按钮。 Since the user will presumably click one of these to select a desired channel, a
Button
makes more sense than a ListView
(much more). 由于用户可能会点击其中一个来选择所需的频道,因此
Button
比ListView
更有意义(更多)。 You can display an image on a Button
along with text, and use the FlatAppearance
properties to style it how you want. 您可以在
Button
上显示图像以及文本,并使用FlatAppearance
属性根据需要设置样式。 Use the Tag
to track the channel ID or the index of the related channel in the collection. 使用
Tag
可以跟踪集合中的通道ID或相关通道的索引。
Finally, use the MouseHover
and MouseLeave
events to manipulate FlatAppearance.BorderSize
and FlatAppearance.BorderColor
to get very close to the first image in the question: 最后,使用
MouseHover
和MouseLeave
事件操作FlatAppearance.BorderSize
和FlatAppearance.BorderColor
以非常接近问题中的第一个图像:
They reside in an scrolling Panel
. 它们位于滚动
Panel
。 The panel width is just a bit wider than the control to avoid the horizontal scrollbar. 面板宽度比控件宽一点,以避免水平滚动条。 As for the buttons, the
HotLight
border (???) is around the entire control rather than just the text. 至于按钮,
HotLight
边框(???)围绕整个控件而不仅仅是文本。 Not what your picture shows you want, but on the other hand, there is nothing involved beyond some standard properties and a little event handling code (5-6 lines). 不是你想要的图片,但另一方面,除了一些标准属性和一些小事件处理代码(5-6行)之外没有任何其他内容。
An ownerdraw ListBox will get you a bit closer to what you want, but ultimately this just makes it look like a ListBox
that has Buttons
in it. ownerdraw ListBox会让你更接近你想要的东西,但最终这只会使它看起来像一个包含
Buttons
的ListBox
。
Place a ListBox on the form , and set these properties: 在表单上放置一个ListBox ,并设置这些属性:
- DrawMode = OwnerDrawFixed - DrawMode = OwnerDrawFixed
- IntegralHeight = False - IntegralHeight = False
- Itemheight = 64 (this is based on the fact that the images are 60x60 in the first image) - 物品高度= 64(这是基于第一张图像中图像为60x60的事实)
- Set the BackColor to ControlLight
or {233,233,233}
for that exact shade of gray as desired. - 根据需要将BackColor设置为
ControlLight
或{233,233,233}
以获得精确的灰色阴影。
As mentioned, ListBox
items do not normally light up when the mouse is over them, so we need some code to track that (like a Button
): 如上所述,
ListBox
项目通常不会在鼠标悬停时点亮,因此我们需要一些代码来跟踪它(如Button
):
Private mouseItem As Int32 = -1
Private Sub lbChannels_MouseMove(sender As Object,
e As MouseEventArgs) Handles lbChannels.MouseMove
Dim ndx = lbChannels.IndexFromPoint(e.Location)
' test to avoid millions of paints
If ndx <> mouseItem Then
If mouseItem <> -1 Then
' invalidate/redraw the OLD itemrect
lbChannels.Invalidate(lbChannels.GetItemRectangle(mouseItem))
End If
mouseItem = ndx
' invalidate/redraw the NEW itemrect
lbChannels.Invalidate(lbChannels.GetItemRectangle(mouseItem))
End If
End Sub
Private Sub lbChannels_MouseLeave(sender As Object,
e As EventArgs) Handles lbChannels.MouseLeave
If mouseItem <> -1 Then
' get rect for what wont be the hot item in a tick
Dim rect = lbChannels.GetItemRectangle(mouseItem)
'lbChannels.Invalidate()
mouseItem = -1 ' no longer Hot
lbChannels.Invalidate(rect)
End If
End Sub
Updated to minimize flickering by redrawing just the items which changed. 更新以通过重新绘制更改的项目来最小化闪烁。
I did not use the MouseHover
event because that fires later, resulting the small (but no where near a second) delay mentioned. 我没有使用
MouseHover
事件,因为它会在稍后触发,从而导致提到的小(但没有接近一秒)延迟。 MouseMove
also makes it easier to get the mouse location. MouseMove
还可以更轻松地获取鼠标位置。
IImageItem IImageItem
Based on comments, you want to auto-generate items based on some other data in the app. 根据评论,您希望根据应用中的其他一些数据自动生成项目。 Rather than assume what that class looks like and to make this easy to implement and applicable to any class, this will use an interface:
这将使用一个接口,而不是假设该类看起来像并使这个易于实现并适用于任何类。
Public Interface IImageItem
Property ID As String ' ???
Property ItemImage As Image
Property Text As String
End Interface
The draw code will require that interface be implemented so it can use those properties to draw your items. 绘制代码将要求实现接口,以便它可以使用这些属性来绘制您的项目。
Id
is an extra one to allow a way to link which ListBox
item is selected or clicked from the collection (only needed if you add items to the ListBox
-- not recommended). Id
是一个额外的一个允许链接从集合中选择或单击哪个ListBox
项目的方法(仅在向ListBox
添加项目时才需要 - 不推荐)。 It could be extended to include an Enabled
property to draw those differently, if needed. 它可以扩展为包含
Enabled
属性,以便在需要时以不同方式绘制它们。 You'd implement this interface on your collection items class thusly: 您可以在集合项类上实现此接口:
Public Class ChannelItem
Implements IImageItem
Public Property ItemImage As Image Implements IImageItem.ItemImage
Public Property Text As String Implements IImageItem.Text
Public Property ID As String Implements IImageItem.ID
' + your existing properties
Public Sub New(txt As String, img As Image, key As String)
Text = txt
ItemImage = img
ID = key
End Sub
Public Overrides Function ToString() As String
Return Text
End Function
End Class
Note: ChannelItem
is my demo version of whatever class you are using to track the channels. 注意:
ChannelItem
是我用于跟踪频道的任何类的演示版本。 Just type Implements IImageItem
on your class, press enter and the IDE will add the properties, set them before adding items to your collection. 只需在类上键入
Implements IImageItem
,按Enter键,IDE将添加属性,在将项添加到集合之前设置它们。
DrawItem Code DrawItem代码
Private Sub lbChannels_DrawItem(sender As Object,
e As DrawItemEventArgs) Handles lbChannels.DrawItem
Dim lb As ListBox = lbChannels
If e.Index < 0 Then
TextRenderer.DrawText(e.Graphics, "", lb.Font, e.Bounds, lb.ForeColor)
Return
End If
Dim iItem As IImageItem
If TypeOf (lb.Items(e.Index)) Is IImageItem Then
iItem = DirectCast(lb.Items(e.Index), IImageItem)
Else
TextRenderer.DrawText(e.Graphics, lb.Items(e.Index).ToString,
lb.Font, e.Bounds, lb.ForeColor)
Return
End If
Dim imgRect As Rectangle = Rectangle.Empty
Dim txtRect As Rectangle
' calc
If iItem.ItemImage IsNot Nothing Then
imgRect = New Rectangle(e.Bounds.X + 1, e.Bounds.Y + 1,
iItem.ItemImage.Width + 2, iItem.ItemImage.Height + 2)
End If
' GetTextExtent
Dim sz = TextRenderer.MeasureText(" " & iItem.Text, lb.Font)
txtRect = New Rectangle(iItem.ItemImage.Width + 4, e.Bounds.Y + 1,
(e.Bounds.Width - iItem.ItemImage.Width) - 8,
e.Bounds.Height - 2)
' Draw Big Box around the text portion
If e.Index = mouseItem Then
Using pR As New Pen(SystemColors.ControlDark, 2),
brB As New SolidBrush(SystemColors.Window)
e.Graphics.DrawRectangle(pR, txtRect)
txtRect.Inflate(-1, -1)
e.Graphics.FillRectangle(brB, txtRect)
End Using
ElseIf (e.State.HasFlag(DrawItemState.Selected)) Then
' ToDo: modify for whatever is desired for the selected item
' this is a guess/example
Using pR As New Pen(SystemColors.Highlight, 2),
brB As New SolidBrush(SystemColors.Window)
e.Graphics.DrawRectangle(pR, txtRect)
txtRect.Inflate(-1, -1)
e.Graphics.FillRectangle(brB, txtRect)
End Using
Else
' could use a channel specific color for each BG
' just extend IImageItem
e.DrawBackground()
End If
If iItem.ItemImage IsNot Nothing Then
e.Graphics.DrawImage(iItem.ItemImage, imgRect)
End If
' recalc TR for where the text really goes
txtRect = New Rectangle(iItem.ItemImage.Width + 4, e.Bounds.Y + 1,
sz.Width + 2, e.Bounds.Height - 0)
TextRenderer.DrawText(e.Graphics, iItem.Text, lb.Font, txtRect, lb.ForeColor)
End Sub
Again, it is not clear whether the darker gray box for "FOX" represents the SelectedItem ,
HotLight`/Hover item or even disabled. 同样,不清楚“FOX”的深灰色框是否代表SelectedItem
,
HotLight` / Hover项目甚至是否已禁用。 The code shows how/where to box the text for the first 2 cases. 该代码显示了前两种情况下如何/在哪里打包文本。 Modify as needed.
根据需要修改。
Usage 用法
' a collection of ChannelItem objects (which implement IImageItem)
Dim channels As New List(Of ChannelItem)
' my fake data
channels.Add(New ChannelItem("More 4", My.Resources.SO_LVImg01, "M4"))
channels.Add(New ChannelItem("Channel 4", My.Resources.SO_LVImg02, "4"))
channels.Add(New ChannelItem("RTE One", My.Resources.SO_LVImg03, "RET1"))
channels.Add(New ChannelItem("FOX", My.Resources.SO_LVImg04, "Fox"))
...
It is all pretty straightforward, just substitute your class for ChannelItem
(it must implement IImageItem
). 这一切都非常简单,只需将您的类替换为
ChannelItem
(它必须实现IImageItem
)。 Rather than copy items into the items collection, you can use that collection as the DataSource
: 您可以将该集合用作
DataSource
,而不是将项目复制到项目集合中:
lbChannels.DataSource = channels
SelectedValue
will be a ChannelItem
object boxed as System.Object
, cast it back to get at all the related data such as a URL or Now Playing text. SelectedValue
将是一个ChannelItem
为System.Object
的ChannelItem
对象,将其System.Object
为获取所有相关数据,例如URL或正在播放文本。
The result: 结果:
In this case, the selected item has a SystemColor.Hightlight
box (blue in my case), and the item the mouse is over has a gray box. 在这种情况下,所选项目有一个
SystemColor.Hightlight
框(在我的情况下为蓝色),鼠标所在的项目有一个灰色框。 There even appears to be the little 2px gap between each item as in the original image. 在原始图像中,每个项目之间甚至会出现小的2px间隙。 This is the result of the image height being a bit less than the
ItemHeight
used. 这是图像高度
ItemHeight
使用的结果。
Putting a border on the things would elide the need to do mouse over highlighting. 在这些东西上设置边框会使得需要将鼠标悬停在突出显示上。
If you want (nearly) total control over how these pseudo buttons appear, you should probably build a UserControl
. 如果你想(几乎)完全控制这些伪按钮的显示方式,你应该建立一个
UserControl
。 Using a Label
and PictureBox
and just the normal events you could get it to do almost anything you want. 使用
Label
和PictureBox
以及正常事件,您可以使用它来完成您想要的任何操作。 You can slap one together in about 20 mins: 你可以在大约20分钟内拍一张:
The Channel
UserControls are contained in an autoscrolling Panel
. Channel
UserControls包含在自动滚动Panel
。 They are basically a custom button, but allows you a great deal of control over the layout, behavior and appearance. 它们基本上是一个自定义按钮,但允许您对布局,行为和外观进行大量控制。 Best of all, each would have its own distinct
Click
event. 最重要的是,每个人都有自己独特的
Click
事件。
1 The reason there are no gaps between items in the LV or LB is to make it easier for users to select an item. 1 LV或LB中的项目之间没有间隙的原因是使用户更容易选择项目。 A gutter or gap opens the chance that the user could click there and get no result.
沟槽或间隙打开了用户可以点击那里并且没有结果的机会。 Or depending on the implementation, your code would crash using a bad index.
或者根据实现,您的代码将使用错误的索引崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.