Выделите элементы ListBox на основе значения из класса

Можно ли перебирать элементы в ListBox и каким-то образом выделять или указывать недоступность элемента, проверяя класс на наличие значения?

По сути, у меня есть класс 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)
                    {

                    }
                }
            }
        }
    }

person Pawel    schedule 05.05.2020    source источник
comment
Почему бы не удалить ненужные элементы (с помощью GameAvailable == false)?   -  person Dmitry Bychenko    schedule 05.05.2020
comment
@DmitryBychenko для формы, в которой пользователи могут отображать все доступные игры, но им нужно указать в списке, какие продукты доступны.   -  person Pawel    schedule 05.05.2020
comment
Что это? WinForms, WPF и т. д.?   -  person    schedule 05.05.2020
comment
@JQSOFT извинения, я должен был упомянуть, что изначально - это WinForms.   -  person Pawel    schedule 06.05.2020


Ответы (1)


Да, это возможно таким образом, как:

  • Свяжите ListBox с GameService.AllGames(), который возвращает, я думаю, список или массив объектов Game.

  • Установите ListBox. DrawMode на DrawMode.OwnerDrawFixed и обрабатывать ListBox.DrawItem для рисования элементов в соответствии с их GameAvailable свойствами.

Предполагая, что имена элементов управления Form1 и listBox1, добавьте в конструктор 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

person Community    schedule 07.05.2020