Notifications
Clear all

[Closed] dotNet listview like multilistbox

I’m trying to re-create the funtionality created for the multilistbox for the dotnet listbox.

I’m having some issues with the port from one to the other.

  1. How to properly removed the selected items in the list when the user his ‘-’.
  2. How to maintain the selecting highlight color when focus is lost.

try(destroyDialog ::rlD)catch()
rollout rlD ""
(	
	local AnimObjs = #()
	local activeFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 10 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local mouseIsDown = off	
	
	fn fnAddItmsLst lst arr = ( -- add Objects to list
		userSel = getCurrentSelection()
		if userSel.count >= 1 do
		(
			for o in userSel do (appendIfUnique arr o)
			lst.items = for i in arr collect i.name -- update list with array
		)
	)
	
	fn fnRemoveItmsLst lst arr = ( -- remove objects from list
		local currSel = lst.selection
		for i = lst.items.count to 1 by -1 where currSel[i] do (deleteItem arr i)
		lst.items = for i in arr collect i.name -- update list with array
		lst.selection = #{}
	)
		
	fn fnClearLst lst arr = ( -- clears list
		for i = lst.items.count to 1 by -1 do (deleteItem arr i)
		lst.items = for i in arr collect i.name -- update list with array
		lst.selection = #{}
	)
	
	
	--DOT NET CONTROLS--------------------------------
	fn fnListviewFactory lv = (
		lv.view = (dotNetClass "System.Windows.Forms.view").details
		lv.Gridlines = true
		lv.Multiselect = true
		lv.fullrowselect = true
		lv.HeaderStyle=lv.HeaderStyle.Nonclickable
		lv.HeaderStyle.Nonclickable 
		slv.addColumns lv #("Name") #(120)	
	)
	
	fn fnAddListItems lv arr = ( -- add Objects to list
		curSel = getCurrentSelection()
		if curSel.count >= 1 do
		(
			for o in curSel do (appendIfUnique arr o)
			
			rows=#()
			
			for i = 1 to arr.count do (
				li = dotNetObject "System.Windows.Forms.ListViewItem" arr[i].name	
				li.Font = activeFont
				append rows li --Added the listViewItem to the rows array
			)
			--clear listview before re-populating
			if lv.items.count > 0 then lv.EnsureVisible 0
			for idx = lv.items.count-1 to 0 by -1 do lv.items.removeat(idx)
			lv.items.addRange rows
		)
	)
	
	fn fnRemoveItems lv arr = (
-- 		idxArr = lv.selectedIndices.Item[0]
-- 		print idxArr
	)
		
	multiListBox lbxAnimatedObjects "Animated Objects" pos:[10,7] width:120 height:12
	dotNetControl lvObjectList "Listview" pos:[140, 10] width:150 height:175
	
	button btnAddAnimObj "+" pos:[60,200] width:30 height:30
	button btnRemoveAnimObjs "-" pos:[90,200] width:30 height:30
	button btnClearAnimObjs "X" pos:[120,200] width:30 height:30	
	
	on lvObjectList mouseDown s a do mouseIsDown = on
	on lvObjectList mouseUp s a do mouseIsDown = off
	on lvObjectList mouseMove s a do	if mouseIsDown and (local item = s.GetItemAt a.x a.y) != undefined do item.selected = on
	on lvObjectList MouseDoubleClick s a do
	(
		itm = s.GetItemAt a.x a.y	
		if itm  != undefined do 
		(
			print itm.text
		)
	)
	

	on lbxAnimatedObjects rightclick do lbxAnimatedObjects.selection = #{}
	on btnAddAnimObj pressed do (
		fnAddItmsLst lbxAnimatedObjects AnimObjs
		fnAddListItems lvObjectList AnimObjs
	)	
	on btnRemoveAnimObjs pressed do (
		fnRemoveItmsLst lbxAnimatedObjects AnimObjs	
		fnRemoveItems lvObjectList AnimObjs
	)
	on btnClearAnimObjs pressed do fnClearLst lbxAnimatedObjects AnimObjs
	on rlD open do (fnListviewFactory lvObjectList)
)
createDialog rlD 300 250 style:#(#style_SysMenu, #style_ToolWindow)

13 Replies

For #2:
This might be overkill – but I had to override the draw method. You can mostly likely find this or similar info in the dotnet thread – it helped me a lot.

   When creating your listview turn ownerdraw on:
lv.OwnerDraw = true -- allows for customization of the list
   Now in your UI rollout you need to add a drawitem function:
on lv drawitem arg do
           (    
               -- set the background of each line
               local selColor = (dotNetClass "System.Drawing.Color").fromARGB 51 153 255 -- a blue default color
               local lvBackColor = selColor.fromARGB 225 225 225
               arg.Item.BackColor = if arg.Item.Selected then selColor else lvBackColor
       
               arg.DrawBackground()
       
               -- set the foreground of each line
  		local brush = 
  		(
  			local brushes = dotNetClass "System.Drawing.Brushes"
  			case arg.Item.Selected of
  			(
  				true: brushes.white
  				false: brushes.black
  			)
  		)
           )
      

*edited for readability

For #1:
Try this

fn AddRangeFn lvObject mxsArr = for i in 1 to mxsArr.count do lvObject.Items.Add (dotNetObject "System.String" mxsArr[i])
fn removeItem arg = 
(
	if if lvObjectList.items.count != 0 and arg.KeyValue == 109 do --or arg.KeyCode.ToString() == "Substract"
	(
		lv_selIdx = (for i = 1 to lvObjectList.SelectedItems.Count collect lvObjectList.SelectedIndices.item[i-1]+1)
		lv_Items = for i in 1 to lvObjectList.Items.Count collect lvObjectList.Items.item[i-1]
		for i = lv_selIdx.count to 1 by -1 do deleteitem lv_Items lv_selIdx[i]
		lvObjectList.BeginUpdate()
		lvObjectList.items.Clear()
		AddRangeFn lvObjectList lv_Items
		lvObjectList.EndUpdate()
	)
)	
dotnet.AddEventHandler lvObjectList "KeyUp" removeItem
2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

why is it so hard?

(@gazybara)
Joined: 11 months ago

Posts: 0

Of course there is always a better solution

I’m working on some hopefully more solid here.

added the remove function
Still not solved the keep ‘highlighted selection’ or the remove items in list yet.


try(destroyDialog ::rlD)catch()
rollout rlD ""
(	
	local AnimObjs = #()
	local activeFont = dotNetObject "System.Drawing.Font" "Microsoft Sans Serif" 10 (dotNetClass "System.Drawing.FontStyle").Regular (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	local mouseIsDown = off	
	
	fn fnAddItmsLst lst arr = ( -- add Objects to list
		userSel = getCurrentSelection()
		if userSel.count >= 1 do
		(
			for o in userSel do (appendIfUnique arr o)
			lst.items = for i in arr collect i.name -- update list with array
		)
	)
	
	fn fnRemoveItmsLst lst arr = ( -- remove objects from list
		local currSel = lst.selection
		for i = lst.items.count to 1 by -1 where currSel[i] do (deleteItem arr i)
		lst.items = for i in arr collect i.name -- update list with array
		lst.selection = #{}
	)
		
	fn fnClearLst lst arr = ( -- clears list
		for i = lst.items.count to 1 by -1 do (deleteItem arr i)
		lst.items = for i in arr collect i.name -- update list with array
		lst.selection = #{}
	)
	
	-----------------------DOT NET CONTROLS--------------------------------
	fn fnListviewFactory lv = (
		lv.view = lv.view.details
		lv.FullRowSelect = lv.GridLines = lv.MultiSelect = on
		lv.HideSelection = off
		lv.HeaderStyle=lv.HeaderStyle.Nonclickable
		lv.HeaderStyle.Nonclickable 
		lv.Columns.add "Name" 130
	)
	
	fn fnAddListItems lv arr = ( -- add Objects to list
		curSel = getCurrentSelection()
		if curSel.count >= 1 do
		(
			for o in curSel do (appendIfUnique arr o)
			
			rows=#()
			
			for i = 1 to arr.count do (
				li = dotNetObject "System.Windows.Forms.ListViewItem" arr[i].name	
				li.Font = activeFont
				append rows li --Added the listViewItem to the rows array
			)
			--clear listview before re-populating
			if lv.items.count > 0 then lv.EnsureVisible 0
			for idx = lv.items.count-1 to 0 by -1 do lv.items.removeat(idx)
			lv.items.addRange rows
		)
	)

	fn fnRemoveItems lv arr = (
	)
	
	fn fnClearList lv arr = (
			if lv.items.count > 0 then lv.EnsureVisible 0
			for idx = lv.items.count-1 to 0 by -1 do lv.items.removeat(idx)
	)
		
	multiListBox lbxAnimatedObjects "Animated Objects" pos:[10,7] width:120 height:12
	dotNetControl lvObjectList "Listview" pos:[140, 10] width:150 height:175
	
	button btnAddAnimObj "+" pos:[60,200] width:30 height:30
	button btnRemoveAnimObjs "-" pos:[90,200] width:30 height:30
	button btnClearAnimObjs "X" pos:[120,200] width:30 height:30	
	
	on lvObjectList mouseDown s a do mouseIsDown = on
	on lvObjectList mouseUp s a do mouseIsDown = off
	on lvObjectList mouseMove s a do	if mouseIsDown and (local item = s.GetItemAt a.x a.y) != undefined do item.selected = on
	on lvObjectList MouseDoubleClick s a do
	(
		itm = s.GetItemAt a.x a.y	
		if itm  != undefined do 
		(
			print itm.text
		)
	)

	on lbxAnimatedObjects rightclick do lbxAnimatedObjects.selection = #{}
	on btnAddAnimObj pressed do (
		fnAddItmsLst lbxAnimatedObjects AnimObjs
		fnAddListItems lvObjectList AnimObjs

	)	
	on btnRemoveAnimObjs pressed do (
		fnRemoveItmsLst lbxAnimatedObjects AnimObjs	
		fnRemoveItems lvObjectList AnimObjs
	)
	on btnClearAnimObjs pressed do (
		fnClearLst lbxAnimatedObjects AnimObjs
		fnClearList lvObjectList AnimObjs
	)
	
	on rlD open do (fnListviewFactory lvObjectList)
)
createDialog rlD 300 250 style:#(#style_SysMenu, #style_ToolWindow)

Looks like I missed a line in my original post (its the last line in the drawitem func) to help you with #2: Also I don’t know how to over-ride the header so I commented it out for now.
Changes in yellow below:

i’ve answered the same question on this forum.

whats wrong with

lv.HideSelection  = false;

exactly ?

lv.HideSelection = off
lv.BackColor = (dotnetclass "System.Drawing.SystemColors").Menu

This should work, It came from Denis!
http://forums.cgsociety.org/showpost.php?p=7403941&postcount=161

Page 1 / 2