Indicating an Empty ListView in C#

Introduction

Have you wondered how you couldshow text in ListView control if it's empty, just like Microsoft doesit in Outlook Express and in some other applications?

Background

OnPaint() won't work

If you're thinking about OnPaint() event,forget it. ListView control is just a wrapper around the control inComCtl and it doesn't fire this event.

UserControl: 100% pure C# solution but complicated

Another clean solution would be to makeyour own UserControl with one ListView and one label on the top whichcould be visible only if ListView would be empty, but there is onelittle problem with column resizing which draws a dark line on thecontrol which goes under the label control which doesn't look veryprofessional. We could possibly cover whole listview background, butthen we would find problems with not showing scrollbars… well, fixingone problem creates another one… and so on…

Using the code

Probably the best solution is tooverride WndProc method with something like this. If m.MSG == 20listview calls function to redraw background, so we just draw somestring on top of it if listView doesn't contain any items.

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 20)
{
if (this.Items.Count == 0)
{
_b = true;
Graphics g = this.CreateGraphics();
int w = (this.Width – g.MeasureString(_msg, this.Font).ToSize().Width)/2;
g.DrawString(_msg, this.Font, SystemBrushes.ControlText, w, 30);
}
}
}

 

Well now it does what we need butsooner or later we will find out that this solution is not perfect. Ifyou will try to resize the whole control, or only one of the columns,or if you add a new item to the listView and part or whole of your textstring will be outside of the column's area, listView will becamepretty messy. Improved overrided WndProc method, which is fixing allthose problems, is here.

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 20)
{
if (this.Items.Count == 0)
{
_b = true;
Graphics g = this.CreateGraphics();
int w = (this.Width – g.MeasureString(_msg, this.Font).ToSize().Width)/2;
g.DrawString(_msg, this.Font, SystemBrushes.ControlText, w, 30);
}
else
{
if (_b)
{
this.Invalidate();
_b = false;
}
}
}

if (m.Msg == 4127) this.Invalidate();
}

Yes, and we shouldn't forget to redraw the whole control on Resize event if listView is empty and showing our text string

private void ListView2_Resize(object sender, EventArgs e)
{
if (_b) Invalidate();
}

Download Source

That's it

 

Up-to-date version of this article can be found on http://www.hasko.com.au/blog/

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!