Empty ListView in C#


Introduction

Have you wondered how you could show text in ListView control if it's empty, just like Microsoft does it 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 in ComCtl and it doesn't fire this event.

UserControl: 100% pure C# solution but complicated

Another clean solution would be to make your own UserControl with one ListView and one label on the top which could be visible only if ListView would be empty, but there is one little problem with column resizing which draws a dark line on the control which goes under the label control which doesn't look very professional. We could possibly cover whole listview background, but then we would find problems with not showing scrollbars...  well, fixing one problem creates another one... and so on...

Using the code

Probably the best solution is to override WndProc method with something like this. If m.MSG == 20 listview calls function to redraw background, so we just draw some string 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 but sooner or later we will find out that this solution is not perfect. If you 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 text string will be outside of the column's area, listView will became pretty messy. Improved overrided WndProc method, which is fixing all those 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();
}
That's it

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


Similar Articles