How to have a multi-coloured items of a ListBox in winforms?

妖精的绣舞 提交于 2019-12-13 16:07:54

问题


I am developing a software in winforms, I am stuck in a step where I have

 List<KeyValuePair<string, string>>. 

and some sample data:

List <KeyValuePair<"S", "1200">>
List <KeyValuePair<"S", "1300">>
List <KeyValuePair<"L", "1400">>

I want to diplay the value of the key pair inside a ListBox, where based in the key of the pair the Item on the ListBox has a diffrent colour, for example if the Key is S, then the Item should be red and if the Key is L the Item should be blue.

Hope you could help me with this.

this is the code I did but it doesn't do what is expected:

        e.DrawBackground();
        Graphics g = e.Graphics;
        Graphics x = e.Graphics;

        g.FillRectangle(new SolidBrush(Color.Olive), e.Bounds);
        x.FillRectangle(new SolidBrush(Color.Aquamarine), e.Bounds);

        foreach (var workOrders in GetItac.FilterWorkOrders())
        {
            if (workOrders.Key == "S")
            {
                g.DrawString(workOrders.Value, e.Font, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y));

            }
            else
            {
                x.DrawString(workOrders.Value, e.Font, new SolidBrush(e.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y));

            }

        }

回答1:


When you need to show customized results in a ListBox control, you need to enable the custom painting of the Items in the list, setting the ListBox DrawMode property to OwnerDrawVariable or OwnerDrawFixed (the latter will set all Items to the same height).
(Note → Here, I'm setting it to OwnerDrawVariable)

The list Items painting has to be performed in the DrawItem event of the ListBox, using the DrawItemEventArgs e.Graphics object. This allow a correct refresh of the Items when the ListBox/Form need repainting.

1 - You don't have to multiply your Graphics object.
2 - The foreach loop is not needed either, because each Item will be painted when you create/modify the ListBox Items collection.

Note → I'm drawing the Items background the way you're showing in your code, but the visual result might be a bit weird (those colors don't blend well).


First, simulate the result of your GetItac.FilterWorkOrders() method, which will return a List<KeyValuePair<string, string>>, add those items Value to the list:

using System.Collections.Generic;

List<KeyValuePair<string, string>> workOrders;

workOrders = new List<KeyValuePair<string, string>>()
{
    new KeyValuePair<string, string>("S", "1200" ),
    new KeyValuePair<string, string>("S", "1300"),
    new KeyValuePair<string, string>("L", "1400")
};
//Select().ToList() extracts the Value string from the KeyValuePair elements
listBox1.DataSource = workOrders.Select(kv => kv.Value).ToList();

You can also code it this way, if that method actually returns a List<KeyValuePair<string, string>>:

workOrders = GetItac.FilterWorkOrders();
listBox1.DataSource = workOrders.Select(kv => kv.Value).ToList();
//Or
workOrders = GetItac.FilterWorkOrders();
listBox1.Items.AddRange(workOrders.Select(kv => kv.Value).ToArray());

When the ListBox Items collection is filled, the DrawItem event will be raised, to allow the painting of the Items content.
You may need to add the MeasureItem event, to be sure to have a correct measure of each Item's height (mandatory, if you plan on modifying the ListBox Font.

For each item that is drawn, the text color is chosen testing the Key of the KeyValuePair<string, string>: if its value is "S", the text color is set to Color.Red, the background color to Color.Olive. Otherwise they're set to Color.Blue and Color.Aquamarine.

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    Color textColor = (workOrders[e.Index].Key == "S") ? Color.Red : Color.Blue;
    Color backColor = (workOrders[e.Index].Key == "S") ? Color.Olive : Color.Aquamarine;
    using (SolidBrush backColorBrush = new SolidBrush(backColor))
    using (SolidBrush foreColorBrush = new SolidBrush(textColor))
    {
        e.Graphics.FillRectangle(backColorBrush, e.Bounds);
        e.Graphics.DrawString(workOrders[e.Index].Value, listBox1.Font, foreColorBrush, 
                              e.Bounds, StringFormat.GenericTypographic);
    }
}

private void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
    e.ItemHeight = listBox1.Font.Height;
}


来源:https://stackoverflow.com/questions/50759508/how-to-have-a-multi-coloured-items-of-a-listbox-in-winforms

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!