Search code examples
c#winformslistboxuser-controls

C# Windows Forms Application ListBox Controls shifted


I'm having problems with an owner drawn listbox in a windows forms application. The listbox is filled with objects containing their own UserControl. The user control of each itemis shown in the listbox. This all works but when I scroll up or down the UserControls appear shifted a bit. Once I click them, they jump to the right position.

enter image description here

In the picture you can see the white UserControls shifted a bit to the right and a bit down.

enter image description here

This is how they look before scrolling.

The list is filled with objects of this type:

class Class1
{
    public UserControl1 UC;
    public string Text;

    public Class1(UserControl1 uc, string text)
    {
        UC = uc;
        Text = text;
    }
}

This is the class that controls the list:

class ListDrawer
{
    public ListBox LB;
    public int HeaderHeight = 25;

    public ListDrawer(ListBox lb)
    {
        LB = lb;
        LB.DrawMode = DrawMode.OwnerDrawVariable;
        LB.DrawItem += LB_DrawItem;
        LB.MeasureItem += LB_MeasureItem;
    }

    private void LB_MeasureItem(object sender, MeasureItemEventArgs e)
    {
        ListBox lst = sender as ListBox;
        Class1 c = (Class1)lst.Items[e.Index];
        e.ItemHeight = HeaderHeight;
        e.ItemHeight = e.ItemHeight + c.UC.Height;
    }

    private void LB_DrawItem(object sender, DrawItemEventArgs e)
    {
        ListBox lst = sender as ListBox;
        Class1 c = (Class1)lst.Items[e.Index];
        e.DrawBackground();
        e.Graphics.FillRectangle(Brushes.DarkSeaGreen, e.Bounds);
        e.Graphics.DrawString(c.Text, LB.Font, SystemBrushes.HighlightText, e.Bounds.Left, e.Bounds.Top);
        if (!lst.Controls.Contains(c.UC))
        {
            lst.Controls.Add(c.UC);
        }
        c.UC.Top = e.Bounds.Top + HeaderHeight;
    }
}

The list is filled on a button click:

    private void button1_Click(object sender, EventArgs e)
    {
        UserControl1 uc = new UserControl1();
        Class1 c = new Class1(uc, "text 1");
        ListDrawer LD = new ListDrawer(listBox1);
        listBox1.Items.Add(c);
        uc = new UserControl1();
        c = new Class1(uc, "text 2");
        listBox1.Items.Add(c);
    }

Hope this can be fixed....

Cheers, Robert.


Solution

  • In the user control override the onMove event:

    protected override void OnMove( EventArgs e ) {
        base.OnMove( e );
    
        this.Parent.Invalidate();
    }
    

    It will probably flicker but will solve your problem