Re: EventArgs and derived classes
- From: ACS <volt9000@xxxxxxxxx>
- Date: Fri, 7 Mar 2008 15:01:41 -0800 (PST)
Hi Peter,
Well thanks to all your help I've finally figured out what's going
on! :)
Turns out that I was assuming SubItem[0] was automatically a SubItemEx
when actually it was just a plain old SubItem.
So I added in some code to ensure that SubItem[0] will always be a
SubItemEx, and now it works perfectly!
Thanks for all your help.
On Mar 5, 11:18 pm, "Peter Duniho" <NpOeStPe...@xxxxxxxxxxxxxxxx>
wrote:
On Wed, 05 Mar 2008 19:41:00 -0800, ACS <volt9...@xxxxxxxxx> wrote:
Hi Pete,
Ok, here's a (hopefully) concise-but-complete listing.
http://utilitybase.com/paste/6152
I've tried to remove everything extra, leaving in only what's
necessary. This single-file code will compile all on its own. The only
stipulation is that two files, named "checked.bmp" and "unchecked.bmp"
should be in the same directory. They can be any valid image, really;
it's enough to demonstrate the problem.
Well, that's not concise or complete. Unless the bitmaps are directly
related to the specific question (and I doubt they are), they don't belong
in the sample, nor does any code that depends on them. That breaks
"concise", and the fact that the images are not included breaks "complete".
It also appears that you're doing customization of the column headers and
sub items. Again, that breaks "concise", since it doesn't really appear
that the customization of the column headers has anything to do with the
customization of the sub items (after all, I was able to post a working
example of customized sub items that didn't touch the column headers).
Also, rather than posting your code somewhere else, you should be
including it in your message. I'll grant that it makes it slightly less
convenient to reference specific lines in the code, but these threads go
in archives, and it's much better for the lifetime of the post to match
the lifetime of any referenced material. The only way to guarantee that
is for all referenced material to be a part of the post.
I'll try to clarify things a bit further:
The event handler ListViewEx_DrawSubItem is correctly being called for
all subitems, including the subitem at index 0 (which is the main
item.)
However, as you will see upon running this program, the main item will
NEVER draw properly. It always draws the default text without any
image, despite my repeated efforts to make it draw as just another
subitem.
If the main item is not represented by a ListViewSubItemEx instance, then
why would you expect it to draw otherwise? And how is the default drawing
not considered "properly", considering that the main "0 column" sub item
isn't your custom class?
In regards to your question, I'm sure that the first if statement
(line 116) is always executing, since the else clause (displaying "No
check." in RED) is never executed. I've further verified this by
replacing Line 127 with a MessageBox statement, and I saw no message
box.
I've even tried stepping through the program line-by-line and found
that when it comes to the if statement on Line 119, the program will
jump back to the beginning of the ListViewEx_DrawSubItem handler, and
then draw the default text in the main item. I don't see why it would
do this-- it seems to be "crashing" at that point (I know not the
right terminology, but I don't know what else to call it.)
Well, that sounds to me as though an exception is happening, but it's
being caught. This isn't necessarily all that unusual. It's possible
that the ListView class is catching the exception, and upon doing so
reverts to default behavior. It's protecting itself from your bug.
So, what is your bug? Well, the most obvious issue is that you're using
"as" but you never bother to check whether the cast succeeded. You might
as well just do a straight cast (and the code likely would be just as
wrong in that case).
It _seems_ to me that a better way to write the handler might be like this:
private void ListViewEx_DrawSubItem(object sender,
DrawListViewSubItemEventArgs e)
{
Graphics g = e.Graphics;
StringFormat fmt = new StringFormat();
fmt.Trimming = StringTrimming.EllipsisCharacter; // Ensure
ellipses appear if the text won't fit
if ((this.Columns[e.ColumnIndex] as ColumnHeaderEx).HasCheckbox ==
true)
{
ListViewSubItemEx subItem = e.SubItem as ListViewSubItemEx;
if (subItem != null && subItem.Checked == true)
g.DrawImage(Image.FromFile(".\checked.bmp"), e.Bounds.Left
+ 1, e.Bounds.Top + 1);
else
g.DrawImage(Image.FromFile(".\unchecked.bmp"),
e.Bounds.Left + 1, e.Bounds.Top + 1);
g.DrawString(e.SubItem.Text, this.Font, new
SolidBrush(Color.Black),
new Rectangle(e.Bounds.Left + 15, e.Bounds.Top,
e.Bounds.Width - 15, e.Bounds.Height), fmt);
}
else
g.DrawString("No check.", this.Font, new
SolidBrush(Color.Red), e.Bounds);
}
However, it seems a bit odd to me that you'd have a column that has the
"HasCheckbox" property set to "true" if the items in that column aren't
your ListViewSubItemEx instances. In fact, why put a special
"ColumnHeaderEx" instance in a column header that won't have a
"ListViewSubItemEx" as the items in that column?
If you made the column headers and sub items correlate better, such that
any column that has an extended header will always have extended sub items
in the column, you'd wind up with code that's more like this:
private void ListViewEx_DrawSubItem(object sender,
DrawListViewSubItemEventArgs e)
{
Graphics g = e.Graphics;
StringFormat fmt = new StringFormat();
ColumnHeaderEx header = Columns[e.ColumnIndex] as ColumnHeaderEx;
fmt.Trimming = StringTrimming.EllipsisCharacter; // Ensure
ellipses appear if the text won't fit
if (header != null && header.HasCheckbox)
{
ListViewSubItemEx subItem = (ListViewSubItemEx)e.SubItem;
using(Image img = subItem.Checked ?
Image.FromFile(".\checked.bmp") :
Image.FromFile(".\unchecked.bmp"))
{
g.DrawImage(img, e.Bounds.Left + 1, e.Bounds.Top + 1);
}
g.DrawString(e.SubItem.Text, this.Font, new
SolidBrush(Color.Black),
new Rectangle(e.Bounds.Left + 15, e.Bounds.Top,
e.Bounds.Width - 15, e.Bounds.Height), fmt);
}
else
g.DrawString("No check.", this.Font, new
SolidBrush(Color.Red), e.Bounds);
}
Finally, in rearranging the above code, I noticed you are a) creating a
new image each time you call this method (inefficient) and b) failing to
dispose the image (VERY bad). I fixed the lack of disposal, but really
you should just be loading the bitmaps once as static elements in the
class that uses them, and then refer to those static instances. Creating
a new image each time the sub item is drawn is just not a good approach.
Hope that helps.
Pete
.
- References:
- EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- Re: EventArgs and derived classes
- From: ACS
- Re: EventArgs and derived classes
- From: Peter Duniho
- EventArgs and derived classes
- Prev by Date: Re: Wanted: minimal Northwind LINQ example
- Next by Date: Re: How to force the program to continue after unhandled exception detection
- Previous by thread: Re: EventArgs and derived classes
- Next by thread: Re: EventArgs and derived classes
- Index(es):
Relevant Pages
|