austinem
austinem

Reputation: 121

Draw images and text in ComboBox

I have a ComboBox in WindowsForms and I draw items manually. Each item is composed from picture and text (Cell.Image and Cell.Title), so item is 34 px height.

My problem is that when I drop down ComboBox, only 1 item is visible. MaxDropDownItems = 4 so ComboBox would draw 4 items. I know that I have set DropDownHeight = 34, but I want to display empty rectangle when there is no item in ComboBox like on the following picture.

ComboBox with no item - OK: ComboBox with no item - OK

ComboBox with only 1 visible item - Bad: ComboBox with only 1 visible item - Bad

My class derived from ComboBox:

public class ComboBoxCells : ComboBox
{
    private List<Cell> _cells;

    public List<Cell> Cells
    {
        get { return this._cells; }
        set
        {
            this._cells = value;
            this.BeginUpdate();
            this.Items.Clear();

            if (value != null)
                this.Items.AddRange(value.ToArray());

            this.EndUpdate();
        }
    }

    public ComboBoxCells()
    {
        this.DrawMode = DrawMode.OwnerDrawVariable;
        this.DropDownHeight = 34;
        this.DropDownWidth = 200;
        this.DropDownStyle = ComboBoxStyle.DropDownList;
        this.MaxDropDownItems = 4;

        this.DrawItem += new DrawItemEventHandler(ComboBoxCells_DrawItem);
        this.MeasureItem += new MeasureItemEventHandler(ComboBoxCells_MeasureItem);
    }

    private void ComboBoxCells_DrawItem(object sender, DrawItemEventArgs e)
    {
        e.DrawBackground();

        // Draw item inside comboBox
        if ((e.State & DrawItemState.ComboBoxEdit) != DrawItemState.ComboBoxEdit && e.Index > -1)
        {
            Cell item = this.Items[e.Index] as Cell;

            e.Graphics.FillRectangle(Brushes.Gray, new Rectangle(e.Bounds.Left + 6, e.Bounds.Top + 6, 22, 22));

            e.Graphics.DrawImage(item.Image, new Rectangle(e.Bounds.Left + 7, e.Bounds.Top + 7, 20, 20));

            e.Graphics.DrawString(item.Title, e.Font,
                    new SolidBrush(e.ForeColor), e.Bounds.Left + 34, e.Bounds.Top + 10);
        }
        // Draw visible text
        else if (e.Index > -1)
        {
            Cell item = this.Items[e.Index] as Cell;

            e.Graphics.DrawString(item.Title, e.Font,
                    new SolidBrush(e.ForeColor), e.Bounds.Left, e.Bounds.Top);
        }

        e.DrawFocusRectangle();
    }

    private void ComboBoxCells_MeasureItem(object sender, MeasureItemEventArgs e)
    {
        e.ItemHeight = 34;
    }
}

Thanks

Upvotes: 2

Views: 6055

Answers (3)

Ctor
Ctor

Reputation: 11

If you set IntegralHeight to true it will resize the drop down list so it doesn't show partial items. It should get rid of the white space.

Upvotes: 1

Priyank
Priyank

Reputation: 10623

In your ComboBoxCells() constructor, add default cell item that can draw white rectangle of 34 px height.

In List<Cell> Cells Set property, remove that item and add new items specified by value.ToArray(). This makes sure that default item is removed whenever list of items are specified, otherwise draw default item.

In your ComboBoxCells_DrawItem() event, handle this change with e.Index = 0 condition and draw the rectangle.

Hope this approach works for you.

Upvotes: 0

John Arlen
John Arlen

Reputation: 6689

DropDownHeight is the number you want to set higher. It is the maximum number of pixels for the drop down box. The system will automatically make it the largest multiple of your item height.

this.DropDownHeight = 200;

Upvotes: 3

Related Questions