根据类中的值突出显示列表框项

时间:2020-05-05 07:19:04

标签: c# winforms loops class listbox

是否可以通过检查类的值来循环遍历ListBox中的项目并以某种方式突出显示或指示项目不可用?

基本上,有一个Game类,并且在存储的信息中有Game是否可用,因此我在遍历ListBox项目时需要检查此类,并以某种方式在ListBox上指示GameAvailable = false。

到目前为止,不确定如何进行:

private void HighlightUnavailable()
    {
        foreach(string item in listbox_consoles.Items)
        {
            foreach (Products.Game game in GameService.AllGames())
            {
                if (item == game.GameName.ToString())
                {
                    if (game.GameAvailable)
                    {

                    }
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

是的,可以通过以下方式实现:

  • 将ListBox绑定到GameService.AllGames(),它将返回一个Game对象的列表或数组。

  • ListBox.DrawMode设置为DrawMode.OwnerDrawFixed并处理ListBox.DrawItem事件,以根据项目的GameAvailable属性绘制项目。

假设控件名称分别为Form1listBox1,请添加Form1构造函数:

public Form1()
{
    InitializeComponent();
    //...

    listBox1.DrawMode = DrawMode.OwnerDrawFixed;
    listBox1.DrawItem += (s, e) => OnListBoxDrawItem(s, e); 
    listBox1.DataSource = GameService.AllGames();
}

假设您要以绿色显示可用的游戏,其余以红色为前景色。

private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
    //Comment if you don't need to show the selected item(s)...
    e.DrawBackground();

    if (e.Index == -1) return;

    var game = listBox1.Items[e.Index] as Game;
    var foreColor = game.GameAvailable ? Color.Green : Color.Red;

    //Pass the listBox1.BackColor instead of the e.BackColor 
    //if you don't need to show the selection...
    TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
        e.Bounds, foreColor, e.BackColor,
        TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}

...或具有不同的背景颜色:

private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index == -1) return;

    var game = listBox1.Items[e.Index] as Game;          

    var backColor = e.State.HasFlag(DrawItemState.Selected)
        ? e.BackColor
        : game.GameAvailable
        ? Color.LightGreen
        : listBox1.BackColor;

    //Or this if you don't need to show the selection ...
    //var backColor = game.GameAvailable
    //  ? Color.LightGreen
    //  : listBox1.BackColor;

    using (var br = new SolidBrush(backColor))
        e.Graphics.FillRectangle(br, e.Bounds);

    TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
        e.Bounds, Color.Black, backColor,
        TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}

...或您的资源中有几张Yes和没有No图像:

Bitmap YesImage, NoImage;

public Form1()
{
    InitializeComponent();
    //...

    YesImage = Properties.Resources.YesImage;
    NoImage = Properties.Resources.NoImage;

    listBox1.DrawMode = DrawMode.OwnerDrawFixed;
    listBox1.DrawItem += (s, e) => OnListBoxDrawItem(s, e);
    listBox1.DataSource = GameService.AllGames();
    this.FormClosed += (s, e) => { YesImage.Dispose(); NoImage.Dispose(); };
}

private void OnListBoxDrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index == -1) return;

    var game = listBox1.Items[e.Index] as Game;
    var backColor = e.State.HasFlag(DrawItemState.Selected)
        ? e.BackColor
        : listBox1.BackColor;
    var bmp = game.GameAvailable ? YesImage : NoImage;
    var rectImage = new Rectangle(
        3, e.Bounds.Y + ((e.Bounds.Height - bmp.Height) / 2),
        bmp.Width, bmp.Height
        );
    var rectTxt = new Rectangle(
        rectImage.Right + 3, e.Bounds.Y,
        e.Bounds.Right - rectImage.Right - 3,
        e.Bounds.Height
        );

    using (var br = new SolidBrush(backColor))
        e.Graphics.FillRectangle(br, e.Bounds);

    e.Graphics.DrawImage(bmp, rectImage);

    TextRenderer.DrawText(e.Graphics, game.GameName, e.Font,
            rectTxt, Color.Black, backColor,
            TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}

SOQ61607771