[Closed] dotnet listview look / feel like MultiListBox ?
I’ve been playing around with the dotnet listview trying to make it look / feel like a MultiListBox control.
The style i’m using is System.Windows.Forms.View.List
The immediate differences are:
1. Even with ‘fullRowSelect’ on, it doesn’t really select a full row – only to the extent of the text.
2. I don’t need to be able to marquee select items yet still be able to click + drag select.
3. the MultiListBox has a black outLine around it which is not a big deal but would be nice to know
If you’re not sure about what I mean, check out the differences in this example code:
(
global lvTestRollout
try(destroyDialog lvTestRollout)catch()
rollout lvTestRollout "lvTestRollout"
(
local ListItems = #("These are some items", "for the example of", "the ListViews", "vs", "the MultiListBox")
dotNetControl lv "System.Windows.Forms.ListView" height:150
multiListBox lb "MultiListBox" height:10
fn initListView =
(
lv.backColor = (dotNetClass "System.Drawing.Color").FromArgb 225 225 225
--The following controls the display of details. We use defaults:
lv.gridLines = true
lv.View = lv.View.List
lv.fullRowSelect = true
lv.hideSelection = false -- show selected objects when listview is not in focus
)
fn fillInListView =
(
theRange = for i in ListItems collect dotNetObject "System.Windows.Forms.ListViewItem" i
lv.Items.AddRange theRange
)
on lvTestRollout open do
(
initListView()
fillInListView()
lb.items = listItems
)
)
createDialog lvTestRollout width:400 height:320
)
EDIT: ok so i’ve answered the first 2 questions a few mins after posting…
It’s not 100% the same but close enough. It seems I need to use System.Windows.Forms.View.Details and add a column for fullRowSelect to work properly which also seemed to solve number 2. Even though you use a marquee selection, it behaves pretty much like the MulitListBox. I’d still prefer not to use the marquee if anyone knows of a way around it but it but as I said it’s close enough for now. Also I still havn’t figured out problem 3…
Hello Joel,
you’ve answered most of your own question already. But this is what i came up with:
lv.View = lv.View.details
lv.columns.add "" --add a column to be able to see the items
lv.columns.item[0].width = lv.width
lv.headerStyle = lv.headerStyle.none --hide the columnheader
lv.borderStyle = lv.borderStyle.none --no border around the control
--lv.borderStyle = lv.borderStyle.fixed3d --default border around the control
--lv.borderStyle = lv.borderStyle.fixedSingle--a single black line around the control
In your example i don’t see a black outline around the multilistbox. The two example-controls look very much alike on my machine. I wouldn’t know how NOT to get the marquee.
Hope it helps,
Klaas
thanks for the headerstyle tip, works great. I’ve made some headway with this since posting. I’ve now got a custom colored selection that remains visible when focus is lost as well as drag / ctrl+drag select / deselect that works like a MultiListBox. Still havn’t gotton rid of that marquee though…
Here’s the updated code if anyone’s interested:
(
global lvTestRollout
try(destroyDialog lvTestRollout)catch()
rollout lvTestRollout "lvTestRollout"
(
local ListItems = #("These are some items", "for the example of", "the ListViews", "vs", "the MultiListBox")
local hitNode
local selMode
local selModeActive = false
local selColor = (dotNetClass "System.Drawing.Color").fromARGB 238 204 85 -- custom selection color (orangey-yellow)
local lvBackColor = selColor.fromARGB 225 225 225
dotNetControl lv "System.Windows.Forms.ListView" height:150
multiListBox lb "MultiListBox" height:10
fn initListView =
(
lv.backColor = lvBackColor
lv.Columns.add "XRef Files:" (lv.width-4)
lv.headerStyle = lv.headerStyle.none --hide the columnheader
lv.Sorting = lv.Sorting.None
lv.View = lv.View.Details
lv.fullRowSelect = true
lv.ownerdraw = true
)
fn fillInListView =
(
theRange = #()
for i = 1 to 2 do join theRange ( for i in ListItems collect dotNetObject "System.Windows.Forms.ListViewItem" i )
lv.Items.AddRange theRange
)
on lv MouseDown arg do if (hitNode = lv.GetItemAt arg.x arg.y) != undefined do
(
if keyBoard.controlPressed then selMode = NOT hitNode.selected
else
(
for i = 1 to lv.SelectedItems.count do lv.SelectedItems.Item[0].selected = false -- clear the selection
selMode = true
)
hitNode.selected = selMode
selModeActive = true
)
on lv MouseMove arg do if selModeActive do
(
hitNode = lv.GetItemAt arg.x arg.y
if hitNode != undefined do hitNode.selected = selMode
)
on lv MouseUp arg do
(
selModeActive = false
if hitNode != undefined do hitNode.selected = selMode
)
on lv ItemSelectionChanged arg do
(
arg.Item.BackColor = if arg.isSelected then selColor else lvBackColor
)
on lv drawitem arg do
(
arg.DrawBackground()
arg.DrawText()
)
on lvTestRollout open do
(
initListView()
fillInListView()
lb.items = listItems
)
)
createDialog lvTestRollout width:400 height:320
)
hi joel,
the dotnet listbox control has a SelectionMode.MultiExtended or a SelectionMode.MultiSimple property that gives it a similar feel to a max multilistbox. I didn’t know if that was something you’d already looked at and dismissed in favour of the listview.
try(destroyDialog lvTestRollout)catch()
rollout lvTestRollout "lvTestRollout"
(
local ListItems = #("These are some items", "for the example of", "the ListViews", "vs", "the MultiListBox")
local hitNode
local selMode
local selModeActive = false
local selColor = (dotNetClass "System.Drawing.Color").fromARGB 238 204 85 -- custom selection color (orangey-yellow)
local lvBackColor = (dotNetClass "System.Drawing.Color").fromARGB 225 225 225
dotNetControl lv "System.Windows.Forms.Listbox" height:150
multiListBox lb "MultiListBox" height:10
on lvTestRollout open do
(
lv.backcolor = lvbackcolor
lv.SelectionMode =(dotnetclass "System.Windows.Forms.SelectionMode").MultiExtended
lv.items.addrange listitems
lb.items = listItems
)
)
createDialog lvTestRollout width:400 height:320
)
Hey Pete,
Thanks for the dotnet listbox info – I hadn’t considered it.
In this case I’d prefer a custom selection color as well. If you know a way of doing that with the listbox that’d be great, otherwise i’ll stick with the listview.
cheers
With the listView control I have just changed the background colour of the selected object in the list. Not sure that you can directly set the colour of the selection.
Hi Joel,
I think this would be possible, if not in max then with an inherited listbox control. I will have a ferret around and see if i can work it out.
Hi Joel,
I think i’ve figured it out. I tried converting the VB code into something max could pallette, but it kept spitting it back at me. It was rejecting a method i was using in visual studio as being not relevant, but that’s probably because i was doing it wrong. In the end I wrote a small inherited control that does does the drawing of the selected node itself. It has a couple of extra properties in there too. Firstly, there is a selecteditemcolor property for the selected background, and also a selecteditemtextcolor property too, in case you need to invert the text or something. If you dont, just set it to the foreground color. here it is –
[left]click the image to download it. there is the MXscript file in the zip too. hope this is what you needed.
[/left]
Paul: Thanks and check the last bit of code that I posted – I’ve already got it working.
Pete: Thanks heaps, your custom control works great. I wish I knew C# so I could do this kind of thing myself.
I just read through my previous posts and it seems i forgot to mention something... I also needed individual control over the ForeColor of items, whether they are selected or not. Again, this is where I wish i knew C#... Can you suggest any good resources to get started in C# ?
Either way I wont trouble you for the ForeColor part, I'm not sure if it'd be so 'easy' with the ListBox since its Items are just strings and not 'ListItem' objects with their own properties. The ListView will be fine - and we've now got a great custom ListBox control too! Thanks again for that.