Search code examples
c#winformslistviewwindows-forms-designerdesign-time

Why does OnDrawItem event for a ListView not affect the Design-time environment?


If I create a class and make it derive from a ListView like this...

class MyListView : ListView
{
    public MyListView() : base()
    {
        DoubleBuffered = true;
        OwnerDraw = true;
        Cursor = Cursors.Hand;
        Scrollable = false;
    }

    protected override void OnDrawItem(DrawListViewItemEventArgs e)
    {
        //base.OnDrawItem(e);
    }
}

Then I open the design view of my windows form and add a new MyListView object then add a single item and link it to a image list. I can see that there is one item in the mylistview object. It has no effect on the object I have on my form called lv of type MyListView. When I run my app on the other hand I see exactly what I expected and there is no items listed.

Why would this effect run-time and not design-time painting?

enter image description here


Solution

  • The answer

    ListViewDesigner shadows OwnerDraw property like Visible or Enabled property of control. So it just works at run-time and changing it doesn't affect design-time.

    Side Note

    If you take a look at source code of ListViewDesigner, you will see this property:

    private bool OwnerDraw
    {
        get { return (bool) base.ShadowProperties["OwnerDraw"]; }
        set { base.ShadowProperties["OwnerDraw"] = value; }
    }
    

    And in PreFilterProperties you will see the designer replaced the original property with this one:

    PropertyDescriptor oldPropertyDescriptor = (PropertyDescriptor) properties["OwnerDraw"];
    if (oldPropertyDescriptor != null)
    {
        properties["OwnerDraw"] = TypeDescriptor.CreateProperty(typeof(ListViewDesigner), 
            oldPropertyDescriptor, new Attribute[0]);
    }
    

    So it doesn't matter what View you use, it performs the default painting regardless of what you have in OnDrawItem. It's because it doesn't use OwnerDraw property at design-time. The designer shadows it. This is the same behavior which you see for Enabled or Visible property.

    Workaround to enable owner-draw at run-time

    As a workaround, you can register a different Designer for your derived control. This way the OwnerDraw property will work as a normal property:

    [Designer(typeof(ControlDesigner))]
    public class MyListView : ListView
    

    Warning: Keep in mind, by registering a new designer for the control, you will lose the current ListViewDesigner features like its designer verbs or its smart tag (actions list) window or Column Sizing options. If you need those features, you can implement those features in a custom designer by looking into ListViewDesigner source code.