PDA

View Full Version : Question about ListView checkboxes


Malkalypse
01-01-2008, 07:49 PM
Okay, I was going through the how-tos, and I came across the 2-part tutorial "How to Develop a Selected Objects Inspector using ListView ActiveX Control". Followed it through, and I actually understand it better than I thought I would.

However, looking at "Where to go from here," it points out that
"The next logical step would be to add an even(t) handler to link the checkbox in the Listview bi-directionally to the .Renderable property." But while I understood the sample script well enough to see what it was doing, I can't seem to figure out how to do that.

Right now I am stuck at

on lv_objects ItemCheck li do
(
for o in selection do (o.Renderable = li.checked)
)

This just turns ALL selected scene objects renderable/not renderable, regardless of what checkbox is selected. How do I tell it to look for a specific checkbox? My problem is not being able to identify the array elements within the listview. When I try to look at the array it just says "IListItem".

As a side note, it appears that ActiveX is in the process of being phased out in favor of DotNet. Should I bother learning to work with the ActiveX Controls at all? I see there is an example for converting the ActiveX ListView Control to the DotNet Listview Control, and I don't care which of these I use (they really don't seem that different), as long as I can figure out how to get at the individual array elements.

Someone who knows about this sort of thing, please help!

Bobo
01-01-2008, 08:21 PM
Having written that tutorial, I guess this is a question for me.

There are a couple possible approaches to do this:

*The ListView is populated based on the current selection. The current version of the script uses the SELECTION collection of objects directly by looping through them, which means that each object in the selection matches the corresponding item in the list. For example, if you changed the selection and it contains the objects Box01, Sphere02 and Cylinder03 in that order, you can be sure that the ListView will also list Box01, Sphere02 and Cylinder03 in that order. Thus, you would have to figure out the INDEX of the item you checked. You can do this by comparing the IListItem returned by the handler with each item in the ListItems array. Just loop from 1 to the number of ListItems and see of the i-th element of the array matches the one you got from the handler. Then take the i-th element from the SELECTION and change its property.

*A variation of the above approach would be to turn the current selection to an array and keep it around to be sure that whatever is checked matches the object stored in the selection snapshot. But this is optional...

*The other approach would be to acquire the node by name - the ListView already contains the name of each object in its second column. Simply get the .text property of the IListItem returned by the handler and call GetNodeByName on it to get to the object it represents. Then set its .renderable property... Obviously, this approach assumes that all objects in the scene are UNIQUELY named!

PEN
01-01-2008, 10:15 PM
Another method could be to use the .tag property of the listView and use the dotNetValue method to store a reference to the node in the tag property. I haven't tried it directly but I believe it should work. Then when that item is selected you can get the tag property and access the corrisponding node. I'm doing this with XML document information that I'm displaying in a treeview. I store the XML doc element in the treeview node so that I can access other properties of the element if they are needed.

Malkalypse
01-02-2008, 12:15 AM
Bobo: I can get the index of the selected objects just fine, but I don't know how to get the index for the corresponding checkboxes. That's what I'm stuck at.

PEN: do you recommend I switch over to DotNet then?

Bobo
01-02-2008, 09:18 AM
Bobo: I can get the index of the selected objects just fine, but I don't know how to get the index for the corresponding checkboxes. That's what I'm stuck at.

PEN: do you recommend I switch over to DotNet then?

You can access ListViewItems by index like a MAXScript array. Note that they are 0-based though. So you can loop from 1 to the number of items in the ListViewItems array and if the (i-1)-th element is equal to the ListViewItem returned in the handler, affect the i-th object.

Even better, the ListViewItem returned by the handler has an .index property which will return 3 for the 3rd item, 10 for the 10th and so on, so you can easily see which one you clicked!

on lv_objects ItemCheck itm do print itm.index

Thus, you can simply use that index to affect the i-th object in the selection:

on lv_objects ItemCheck itm do
(
selection[itm.index].renderable = itm.checked
)

PEN
01-02-2008, 12:14 PM
Bobo: I can get the index of the selected objects just fine, but I don't know how to get the index for the corresponding checkboxes. That's what I'm stuck at.

PEN: do you recommend I switch over to DotNet then?

You have to if you are planning on using Max past Max 9. AX controls will work on 9 but not 2008. dotNet was implimented for Max 9 and in my opinion it is far better then AX.

Malkalypse
01-02-2008, 06:46 PM
Bobo, thanks! I will try that as soon as I get home.

PEN, really? Wow, that's kind of a jolt, especially considering how little documentation there is for DotNet compared to ActiveX. I agree that DotNet does seem superior in terms of both range and efficiency. Fortunately, it seems that most of what I have been learning (so far) for ActiveX will transfer over.

Bobo
01-02-2008, 07:50 PM
Bobo, thanks! I will try that as soon as I get home.

PEN, really? Wow, that's kind of a jolt, especially considering how little documentation there is for DotNet compared to ActiveX. I agree that DotNet does seem superior in terms of both range and efficiency. Fortunately, it seems that most of what I have been learning (so far) for ActiveX will transfer over.

Keep in mind ActiveX was added in Max 4 and I spent many years between Max 5 and 8 adding examples, documentation of ListView and TreeView controls, How To... examples and whatnot. Obviously, I needed time to learn these things myself in order to write up more. DotNet is a VAST topic and documenting every possible control would be a huge task and a vaste of time, because there are methods for asking for methods, handlers, properties etc. of DotNet controls and you should be able to find out whatever you need. I also dumped some data on my site (http://www.scriptspot.com/bobo/mxs9/dotNet/DotNetControls.html) but cannot incorporate it into the Help because of the size...

What happened was that Microsoft decided to phase out ActiveX in favour of DotNet and thus did not recompile most typical ActiveX control for WinXP64 and Vista. In Max 9, all tools that used ActiveX controls like the Render To Texture and Named Sel.Set Editor were rewritten to use DotNet controls instead.

At this point, it is a good idea to learn how DotNet controls work. There are some bad things about them (for example, a double-click on DotNet ListView always triggers a checked event and is tricky to handle the same as the AX version), but in general DotNet is much better, more powerful and has a large number of standardized controls you can start using immediately.

RustyKnight
01-02-2008, 10:41 PM
Just to confuse the matter, although Bobbo has actually made a point of it indirectly, it may not have stood out...

The index of a list view item IS NOT THE SAME as the index of the selection collection...

ie, you can't do listViewItems[index] == selection[index]...this is invalid...or can be...

ListView's tend to sort the list internally...

I just thought I'd make a point of it...as I was caught be this a while back...

Also, DoNet is well document...it just takes a little work and time to get it to work in max...much better documentation then activeX (outside of max that is)...just my opinion

Shane

Malkalypse
01-03-2008, 05:31 AM
Okay, I have a (very) basic understanding of the ActiveX listview now.. what about the DotNet version? I can't use

on lv_objects ItemCheck li do (selection[li.index].renderable = li.checked)

because there is no ItemCheck. What do I use instead? This is where the lack of documentation becomes a problem (don't worry, Bobo, I'm not blaming you. As you said, you have had a much longer time to go into the ActiveX controls.)

And Rusty.. yeah, the problem is I AM looking for documentation inside Max. And beyond that, well it's hard to find anything when you don't know what you're looking for. =P

RustyKnight
01-03-2008, 05:50 AM
Okay, I have a (very) basic understanding of the ActiveX listview now.. what about the DotNet version? I can't use

on lv_objects ItemCheck li do (selection[li.index].renderable = li.checked)

because there is no ItemCheck. What do I use instead? This is where the lack of documentation becomes a problem (don't worry, Bobo, I'm not blaming you. As you said, you have had a much longer time to go into the ActiveX controls.)

And Rusty.. yeah, the problem is I AM looking for documentation inside Max. And beyond that, well it's hard to find anything when you don't know what you're looking for. =P
Fair call, but you might want to do a couple of things...
firstly check out http://msdn2.microsoft.com/en-us/library/ms229335.aspx
It's the dot net class library...lots of fun ;)
Secondly check out http://forums.cgsociety.org/showthread.php?f=98&t=551473, which is the dotNet forum thread ;)

Now to the question...

on lv_objectsItemChecked itemCheckedEventArgs do (...) -- DotNet 2.00
on lv_objectsItemCheck itemCheckedEventArgs do (...)
Okay, the ItemCheckedEventArgs is a reference to the same named dotnet class which contain a number of interesting properties, including;
CurrentValue - Gets a value indicating the current state of the item's check box.
Index - Gets the zero-based index of the item to change.
NewValue - Gets or sets a value indicating whether to set the check box for the item to be checked, unchecked, or indeterminate.
I'd ignore the NewValue for the time begin...

I hope this helps you get a little further...

edt: Forgive any "shortness" in my response, I've been bagging my head against a rather annoying sdk problem for the past couple of weeks and I'm really rather tired....however, I looked most of this up in around 10 minutes ;) but I've played with listview and treeview a bit ;)

Malkalypse
01-04-2008, 01:24 AM
Okay, I'm still missing something.

on lv_objects itemChecked itemCheckdEventArgs do (...)

What goes in the brackets? How do I explain to DotNet what I am trying to do? In ActiveX terms it would be (selection[li.index].renderable = li.checked), but when I try it with ActiveX it doesn't know what "li" is. I try "print li" and it comes up undefined. I tried switching to

on lv_objects itemChecked itemCheckdEventArgs li do (...)

and it at least identifies li as objects:System.Windows.Forms.ListView. However, li.index is a bit of a problem.. I get the error:

Unknown property: "index" in dotNetObject:System.Windows.Forms.ItemCheckedEventArgs

So what do I use instead? Is it just a different phrasing I need to learn, or should I approach this in a different way?

RustyKnight
01-04-2008, 01:36 AM
Okay, I'm still missing something.

on lv_objects itemChecked itemCheckdEventArgs do (...)

What goes in the brackets? How do I explain to DotNet what I am trying to do? In ActiveX terms it would be (selection[li.index].renderable = li.checked), but when I try it with ActiveX it doesn't know what "li" is. I try "print li" and it comes up undefined. I tried switching to

on lv_objects itemChecked itemCheckdEventArgs li do (...)

and it at least identifies li as objects:System.Windows.Forms.ListView. However, li.index is a bit of a problem.. I get the error:

Unknown property: "index" in dotNetObject:System.Windows.Forms.ItemCheckedEventArgs

So what do I use instead? Is it just a different phrasing I need to learn, or should I approach this in a different way?Okay, firstly, you can't arbitrarily add event parameters. Maxscript is clever, but is not that clever...

Now, I think I mentioned in my previous post, that itemCheckdEventArgs was a reference to System.Windows.Forms.ItemCheckdEventArgs class, which has a property called index, which, "Gets the zero-based index of the item to change"...straight from the dotnet docs.

So armed with this information, we should be able to do something like this:
on lv_objects itemChecked itemCheckdEventArgs do (

local index = itemCheckdEventArgs.index
local li = lv_objects.Items.item[index]

-- You have to remember that the index is zero based...
selection[index + 1].renderable = li.checked

)
Now, I've not tested this

Shane

PEN
01-04-2008, 02:05 AM
Ya dotNet uses 0 based arrays as do most if not all other languages that I have used and Max script is 1 based so...

theListItem.index==theMaxArray[theListItem.index+1]

Sorry I don't have time right now to look over your code. I will have a look tomorrow. I have been using listView and treeView a lot in my latest work.

Malkalypse
01-04-2008, 02:20 AM
Okay, firstly, you can't arbitrarily add event parameters. Maxscript is clever, but is not that clever...

Don't worry, I don't make a practice of it. My thinking in this was "what is missing from what I have here, that was in the original version?" And the ActiveX version DID have a parameter in there for the listview item in question. It was a little desperate maybe, but no harm done, and it DID make the statement recognize what I was talking about...

Now, I've not tested this

I tested it, and I'm getting some wierd results. It starts on the SECOND time the value is changed, and has the reverse effect I want it to (i.e. checked -> not renderable; not checked -> renderable). Also, it causes directly changing the value (i.e. going into the properties and switching it on or off) not to work.

RustyKnight
01-04-2008, 04:19 AM
Don't worry, I don't make a practice of it. My thinking in this was "what is missing from what I have here, that was in the original version?" And the ActiveX version DID have a parameter in there for the listview item in question. It was a little desperate maybe, but no harm done, and it DID make the statement recognize what I was talking about...



I tested it, and I'm getting some wierd results. It starts on the SECOND time the value is changed, and has the reverse effect I want it to (i.e. checked -> not renderable; not checked -> renderable). Also, it causes directly changing the value (i.e. going into the properties and switching it on or off) not to work.

My bad, I think I was reading the wrong class entry...


on lv_objects ItemChecked itemCheckedEventArgs do (

local listViewItem = itemCheckedEventArgs.item
local index = listViewItem.index

selection[index + 1].renderable = listViewItem.checked

)
This should work, I tested it against the "Converting ActiveX ListView Control to DotNet ListView Control" sample.

The other change I would encourage you to make is in the "fillInSpreadSheet" method, in the main object loop, addli.checked = o.renderableThis will set the checkbox to an initial state that makes sense within the context of the scene...this might account for your second issue ;)

Shane

Malkalypse
01-04-2008, 04:39 AM
Okay, it's working now. I understand it less than I would like to, but now that I have something that works, I can try to get a better grip on it. I will go through a couple more tutorials, and will definitely check out both the Microsoft site and the DotNet thread here.

(oh, and I already had the li.checked = o.renderable built into my fillInSpreadsheet function :) )

Thanks for the help, and that part goes for Bobo and PEN as well!

CGTalk Moderation
01-04-2008, 04:39 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.