[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.
- How to properly removed the selected items in the list when the user his ‘-’.
- 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)
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
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:
Have you seen this thread? It may help you.
 http://forums.cgsociety.org/showthread.php?f=98&t=689249&page=1&pp=15 
Particularly one of the last posts:
 http://forums.cgsociety.org/showpost.php?p=5482749&postcount=23 
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