Список нарисованный владельцем не рисует ранее выбранный элемент

Я хочу увеличить высоту элементов в списке - в основном, чтобы добавить их. Кроме этого, я не хочу изменять поведение списка по умолчанию. Я следовал примеру MSDN для создания списков, нарисованных владельцем, но у меня проблема. В списке по умолчанию элементы отображаются черным, а выбранный элемент - белым с синей подсветкой. Для реализации той же функциональности я использовал следующий код в обработчике события DrawItem:

private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        Brush b = (e.Index == ((ListBox)sender).SelectedIndex ? Brushes.White : Brushes.Black);
        e.DrawBackground();
        e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, b, new Rectangle(new Point(e.Bounds.X, e.Bounds.Y + 2), e.Bounds.Size));
        e.DrawFocusRectangle();
    }

Кажется, это работает нормально, кроме случаев, когда я нажимаю на список. Выбранный элемент отображается белым текстом на синем фоне, но ранее выбранный элемент остается белым. Кажется, что элемент, который я выбрал, перерисован, но ранее выбранный элемент - нет. Если я перехожу к другому элементу управления, список перерисовывается нормально. Что мне не хватает?

2 ответа

Чтобы добавить отступ к списку, просто установите.ItemHeight списка на некоторую высоту.

В противном случае, если вы хотите сделать рисование владельцем, вместо того, чтобы выбирать цвет вручную, используйте e.ForeColor. Как это:

Brush b = new SolidBrush(e.ForeColor);

Обратите внимание, что в этом случае вам придется рисовать фон и для выбранного элемента. Проверка состояния элемента списка может быть выполнена следующим образом:

e.Graphics.FillRectangle((e.State & DrawItemState.Selected) != 0 ? SystemBrushes.Highlight : SystemBrushes.Window, new Rectangle(new Point(e.Bounds.X, e.Bounds.Y + 2), e.Bounds.Size));

Ответ: ListBox.SelectedIndex очень иррационально (как сказал Ганс), но e.ForeColor достаточно правильно. Используйте это вместо этого.

Замените свой код: e.Index == ((ListBox)sender).SelectedIndex

с e.ForeColor == SystemColors.HighlightText

Вспомогательные данные:

Добавьте эту строку в начало listBox1_DrawItem:

Console.WriteLine("e.Index=" + e.Index + " SelectedIndex=" + 
  listBox1.SelectedIndex + " ForeColor=" + e.ForeColor);

Это производит вывод как это ( // аннотированный)

// Added 4 items to listbox
e.Index=0 SelectedIndex=-1 ForeColor=Color [WindowText]
e.Index=1 SelectedIndex=-1 ForeColor=Color [WindowText]
e.Index=2 SelectedIndex=-1 ForeColor=Color [WindowText]
e.Index=3 SelectedIndex=-1 ForeColor=Color [WindowText]

// MouseDown on item 0
e.Index=0 SelectedIndex=-1 ForeColor=Color [WindowText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=1 SelectedIndex=0 ForeColor=Color [WindowText]
e.Index=2 SelectedIndex=0 ForeColor=Color [WindowText]
e.Index=3 SelectedIndex=0 ForeColor=Color [WindowText]
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
// MouseUp on item 0 (no DrawItem events)

// MouseDown for item 1
e.Index=0 SelectedIndex=0 ForeColor=Color [HighlightText]
e.Index=0 SelectedIndex=0 ForeColor=Color [WindowText]
e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
// MouseUp for item 1 (no DrawItem events)

// MouseDown for item 2
e.Index=1 SelectedIndex=1 ForeColor=Color [HighlightText]
e.Index=1 SelectedIndex=1 ForeColor=Color [WindowText]
e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]
e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]

// Drag to item 3
e.Index=2 SelectedIndex=2 ForeColor=Color [HighlightText]
e.Index=2 SelectedIndex=2 ForeColor=Color [WindowText]
e.Index=3 SelectedIndex=3 ForeColor=Color [HighlightText]
e.Index=3 SelectedIndex=3 ForeColor=Color [HighlightText]
// MouseUp over item 3 (no DrawItem events)

Так что в основном... ListBox может рисовать больше, чем мы хотим, но в итоге вы получите правильные цвета во время последнего рисования.

Я также рекомендую DoubleBuffering.

Другие вопросы по тегам