Настройка элемента списка (по индексу) полужирным шрифтом

Я пытаюсь установить все текущие доступные элементы в listbox жирным шрифтом. И когда элементы будут добавлены позже, они будут иметь шрифт по умолчанию. Таким образом, пользователь может наглядно видеть первоначальные перечисленные элементы и новые.

Из конструктора формы я заполняю свой список следующим образом, это начальные значения, которые добавляются.

Private Sub FillLinkedBox(ByVal oReferenceList As String())

    ' Fill the linked listbox with the current linked items
    Debug.Print(oReferenceList.ToString)
    lbLinkedParameters.Items.AddRange(oReferenceList)

    ' Set the font of all the existing items in the listbox
    For i As Integer = 0 To lbLinkedParameters.Items.Count - 1

       ' Set the font to bold for these items.

    Next

End Sub

После того, как пользователь закончит, я также хотел бы проверить шрифт элементов при обработке, чтобы я мог определить, что было начальным значением, а что нет (но я также мог бы сохранить список в памяти и проверить, указан ли элемент), если проверка шрифта это не хороший вариант.

Если вы нашли этот сообщение, описывающее что-то, что должно делать эта операция, но она основана на событии; и я не понимаю, как это работает.

Dim buttonPressed As Boolean
Private Sub ListBox1_DrawItem(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
e.DrawBackground()

    If ListBox1.SelectedIndices.Contains(e.Index) And buttonPressed Then
        e.Graphics.DrawString(ListBox1.Items(e.Index), e.Font, Brushes.Green, e.Bounds.X, e.Bounds.Y)

    Else
        e.Graphics.DrawString(ListBox1.Items(e.Index), e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y)
    End If
    If e.Index = ListBox1.Items.Count - 1 Then
        buttonPressed = False
    End If
    e.DrawFocusRectangle()
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    buttonPressed = True
    ListBox1.Refresh()
End Sub

Мой вопрос: как изменить шрифт элемента списка по заданному индексу?


person Mech_Engineer    schedule 28.04.2016    source источник
comment
Вместо этого попробуйте использовать Datagridview. Легче форматировать строки и ячейки   -  person F0r3v3r-A-N00b    schedule 28.04.2016
comment
Верно, но это можно сделать с помощью ListBox с относительно низкой сложностью.   -  person Vincent Thacker    schedule 28.04.2016


Ответы (2)


it's based on an event; and I don't understand how it works.

Если вы установите для ListControl (List/Combo) значение OwnerDraw, событие DrawItem запускается каждый раз, когда Windows нужно нарисовать элемент; вы можете предоставить код для изменения цвета, шрифта или других действий.

After the user is finished I would also like to test the items font when processing

Проблема в том, что шрифт основан на состоянии элемента. Как вы описали, то есть является ли элемент оригинальным или добавленным. Это состояние нельзя определить по индексу, и вы не можете впоследствии переопределить это состояние по визуальному элементу, например по тому, как что-то было отрисовано (да и не должны).

Таким образом, задача на самом деле состоит из двух связанных вещей:

  1. Показать пользователю, какие элементы являются новыми/добавленными
  2. Отслеживайте их как-то, чтобы код мог их определить

Это будет использовать интерфейс, который вы можете добавить к любому классу. Это делает решение менее специфичным для этого локализованного случая.

Public Interface IListItem
    Property Selected As Boolean
    Function GetDisplayText() As String  ' not really needed
End Interface

Код будет использовать Selected для отслеживания и отрисовки добавленных элементов. Измените имя, если хотите, но вам также придется изменить код розыгрыша.

Public Class SimpleThing
    Implements IListItem

    ' your stuff
    Public Property Name As String
    Public Property Value As Int32
    Public Property Foo As Int32
    Public Property Bar As Single     

    Public Property Selected As Boolean Implements IListItem.Selected

    Public Sub New(n As String, v As Int32, 
                Optional b As Boolean = True)
        Name = n
        Value = v
        Selected = b
    End Sub

    Public Function GetDisplayText() As String Implements IListItem.GetDisplayText
        Return Name
    End Function

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class

GetDisplayText должен разрешить другой вывод текста, когда элемент отображается в ListControl, по сравнению с другими ситуациями. Это не жесткое требование.

SimpleThing может хранить любую информацию об этих вещах, которая вам нужна, чертеж ListBox/ComboBox зависит только от элементов IListItem. Вы можете заполнить элемент управления, используя список как DataSource:

ListThings = New List(Of SimpleThing)
...
ListThings.Add(New SimpleThing("Able", 42, True))
ListThings.Add(New SimpleThing("Baker", 7, True))
...
ListThings.Add(New SimpleThing("Ziggy", 6, True))

lbEnabler.DataSource = ListThings
lbEnabler.DisplayMember = "Name"
lbEnabler.ValueMember = "Value"

Элемент управления пользовательского интерфейса установлен на OwnerDrawFixed и использует этот код для рисования элементов:

Private Sub lst_DrawItem(sender As Object, 
                    e As DrawItemEventArgs) Handles lbEnabler.DrawItem
    Dim lb As ListBox = CType(sender, ListBox)
    If e.Index < 0 Then
        TextRenderer.DrawText(e.Graphics, "", lb.Font, e.Bounds, lb.ForeColor)
        Return
    End If

    Dim bg As Color = If(e.State.HasFlag(DrawItemState.Selected),
                         SystemColors.Highlight, SystemColors.Window)
    Dim fg As Color = If(e.State.HasFlag(DrawItemState.Selected),
                         SystemColors.HighlightText, SystemColors.WindowText)

    Dim iItem As IListItem
    If TypeOf lb.Items(e.Index) Is IListItem Then
        iItem = CType(lb.Items(e.Index), IListItem)
    Else
        TextRenderer.DrawText(e.Graphics, lb.Items(e.Index).ToString, lb.Font, e.Bounds,
                              fg, bg, TextFormatFlags.Left Or
                              TextFormatFlags.VerticalCenter)
        Return
    End If
    e.DrawBackground()

    If iItem.Selected Then            ' change to IsOrginal or IsBold
        Using f As New Font(lb.Font.FontFamily, lb.Font.Size, FontStyle.Bold)
            TextRenderer.DrawText(e.Graphics, iItem.GetDisplayText(), f, e.Bounds,
                                  fg, bg, TextFormatFlags.Left Or
                                  TextFormatFlags.VerticalCenter)
        End Using
    Else
        '  default
        TextRenderer.DrawText(e.Graphics, iItem.GetDisplayText(), lb.Font, e.Bounds,
                              fg, bg, TextFormatFlags.Left Or
                              TextFormatFlags.VerticalCenter)
    End If

End Sub

Результат:

введите здесь описание изображения

Лично я не думаю, что это очень хорошая презентация. Это нестандартно, и то, что обозначает Жирный шрифт, не сразу очевидно. Однако вы можете делать с событием DrawItem все, что захотите, например добавить графический индикатор:

введите здесь описание изображения

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

Dim added = myListBox.Items.
                Cast(Of SimpleThing).
                Where(Function(f) f.Selected).
                ToArray()
person Ňɏssa Pøngjǣrdenlarp    schedule 28.04.2016
comment
Если это ответ на вопрос, нажмите на галочку, чтобы он был перемещен из списка «Неотвеченные». - person Ňɏssa Pøngjǣrdenlarp; 03.06.2016

Создайте переменную шрифта и настройте любой элемент в вашем ListBox, где e.Index — это номер элемента, который вы хотите изменить.

Dim useFont as Font = e.Font
    Select Case e.Index
        Case 0
            'Set Font to Bold
          useFont = New Font(e.Font, FontStyle.Bold)
    End Select

    ' Draw the current item text based on the current  
    ' Font and the custom brush settings.
    e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), _
    useFont, e.Brush, e.Bounds, StringFormat.GenericDefault)
person Vincent Thacker    schedule 28.04.2016
comment
что такое e? аргументы события, как показано в моем вопросе? - person Mech_Engineer; 28.04.2016