First, let me point out that I’m not a UI person. I don’t like doing them becasue they don’t interest me, and I usually find it to be mostly grunt work, nothing interesting. Because I don’t do UI, I’m only vaguely aware of UI component shortcomings in the CF. Sure I know several from newsgroup reports, but I’ve not been really bitten by one – until this weekend that is.
I’m working on a project that has a seeminly simple UI requirement – a two column list of items. In column 1 is a checkbox, and column 2 is text, preferrably a LinkLabel. The user can “check” multiple items to remove them from the list with the click of another button, or a click on the text should send them to the detail view of that item. Simple use of a ListView in detail mode with Checkboxes enabled, right? I can already see the seasoned CF UI developer smiling….
Take 1: Drop on a ListView, turn on CheckBoxes and FullRowSelect , and run
Interesting. Every time I tap on a row, the checkbox state toggles. Who’s bright idea was that? I recall the behavior from the newsgroups, so I Google for a workaround. Nothing proposed to actually fix it, just ideas for different presentation. I’m not giving up that easily, I want it to work the way it should.
Take 2: Screw around with P/Invoking ListView Messages
My first thought is that maybe I can find if the user clicked (keep it to yourself, the problem with this idea isn’t discovered until Take 4) on the checkbox itself, so I need to determine where its bounds are. Tried LVM_GETCOLUMNWIDTH and LVM_GETITEMRECT. Seems that the checkbox isn’t a column itself, and there are no APIs I can come up with to get it. Ugh – I’ve now burned an hour on something that should be simple, and of course now I can’t just let it be.
Take 3: Use my own icon
While playing with the APIs I saw that LVM_GETITEMRECT can get the position of the icon, so in theory I could get the tap position, then use that to find out if it’s on the icon, and swap the icon. I created my icons, added them to a ImageList, removed the Checkboxes and loaded the list. All is looking good. I also noticed that LVM_HITTEST can tell me if the icon was tapped without a check for bounds, so I’ll implement that once I get thetap location.
Take 4: Added MouseDown and MouseUp handlers
Of course Studio says they’re available, but I get nothing. Maybe it’s becasue I’m using the RTM CF. SP2 fixed a lot, so I’ll add that. While I’m att it I’ll add handling in the app to ensure that SP2 is applied in order to run the app.
Take 5: Added the SP2 handler first, then found out that SP2 still didn’t add the events. Crap. Who made the decisions on what would be supported with this control and did he or she have and clue about how this f’ing control was used in the real world?
So at midnight on Sunday I packed it in. Next step: unless someone recommends or provides a much simpler solution, I’m going to add an IMessageFilter implementation (fortunately I added that for OpenNETCF or I’d really be screwed), use that to get my mouse location, then use that location with the LVM_HITTEST to see if the icon was tapped, and if it was toggle its state, otherwise navigate. With all this work I should have just done an implementation of the OwnerDrawnList. To think I didn’t do that because I wanted something simple and easy to implement.