Рейтинг:
6
Mike Meinz
успешный пример - Пересмотрено 5 сентября 2013 года 10:57 EDT, чтобы включить RemoveAt
Следующий код работает.
Я тестировал с помощью Visual Studio 2012 на ПК с Windows 8.
С помощью интерактивного отладчика Visual Studio я определил, что все видимые строки в ListBox
обновляются при добавлении новой строки и что если новая строка не видна, то она не рисуется. Поэтому мне пришлось сохранить цвет кисти для каждой строки в коллекции до добавление новой строки и использование этого цвета кисти каждый раз, когда рисуется связанная строка списка. Я использую класс Collection для сохранения цветов кисти для каждой строки списка.
То Refresh
метод был не нужен.
Dim colColors As Collection = New Collection ' Space to save brush colors for each row in the ListBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ListBox1.DrawMode = DrawMode.OwnerDrawFixed
End Sub
Private Sub listbox_add_Blue()
SetColorForNewRow(Brushes.Blue)
ListBox1.Items.Add("Blue") ' adds the line to the list box
End Sub
Private Sub listbox_add_Black()
SetColorForNewRow(Brushes.Black)
ListBox1.Items.Add("Black") ' adds the line to the list box
End Sub
Sub listbox_remove_0()
If ListBox1.Items.Count < 1 Then Exit Sub
' Must remove brush color from colColors collection first!
colColors.Remove(1) ' Collection index starts at 1
ListBox1.Items.RemoveAt(0)
End Sub
Private Sub ListBox1_DrawItem(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
e.DrawBackground()
If e.Index >= 0 AndAlso e.Index < ListBox1.Items.Count Then
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), _
e.Font, colColors.Item(1 + e.Index), _
e.Bounds, StringFormat.GenericDefault)
End If
e.DrawFocusRectangle()
End Sub
Sub SetColorForNewRow(ByVal MyBrush As Brush)
colColors.Add(MyBrush)
End Sub
Private Sub btnBlack_Click(sender As Object, e As EventArgs) Handles btnBlack.Click
listbox_add_Black()
End Sub
Private Sub btnBlue_Click(sender As Object, e As EventArgs) Handles btnBlue.Click
listbox_add_Blue()
End Sub
Private Sub btnRemove_Click(sender As Object, e As EventArgs) Handles btnRemove.Click
listbox_remove_0()
End Sub
_____________________________________________________________________________________________
Первая попытка использовать массив для хранения цветов кисти (частичный успех)
Следующий код работает для небольшого количества элементов в
ListBox
Я тестировал с помощью Visual Studio 2012 на ПК с Windows 8. Я все еще изучаю, как обращаться с этим
DrawItem
событие, когда активна вертикальная полоса прокрутки.
С помощью интерактивного отладчика Visual Studio я определил, что все строки в
ListBox
обновляются при добавлении новой строки. Поэтому мне пришлось сохранять цвет кисти для каждой строки в массиве и использовать этот цвет кисти каждый раз, когда перерисовывается связанная строка списка. То
Refresh
метод был не нужен.
Это было бы намного проще с a
ListView
контроль.
Dim blue_message As Boolean = False ' Use Black or Blue Brush
Dim AddMode As Boolean = False ' Tells DrawItem that it is in Add to ListBox mode
Dim intNewIndex As Integer ' The index of the new item to be added to the ListBox
Dim arrColors(0 To 100) As Brush ' Space to save brush colors for each row in the ListBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ListBox1.DrawMode = DrawMode.OwnerDrawFixed
End Sub
Private Sub listbox_add_Blue()
blue_message = True
AddMode = True
intNewIndex = ListBox1.Items.Count
ListBox1.Items.Add("Blue") ' adds the line to the list box
End Sub
Private Sub listbox_add_Black()
blue_message = False
AddMode = True
intNewIndex = ListBox1.Items.Count
ListBox1.Items.Add("Black") ' adds the line to the list box
End Sub
Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
Dim myBrush As Brush = Brushes.Black
e.DrawBackground()
If AddMode AndAlso e.Index = intNewIndex Then
If blue_message Then
myBrush = Brushes.Blue
End If
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), e.Font, myBrush, _
e.Bounds, StringFormat.GenericDefault)
If e.Index > arrColors.GetUpperBound(0) Then ' Is the array filled
ReDim Preserve arrColors(0 To arrColors.Count + 100) ' Make some more room
End If
arrColors(e.Index) = myBrush ' Save which brush we used
AddMode = False ' Finished drawing the new item (It is the last row of the ListBox
Else
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), _
e.Font, arrColors(e.Index), _
e.Bounds, StringFormat.GenericDefault)
End If
e.DrawFocusRectangle()
End Sub
Private Sub btnBlack_Click(sender As Object, e As EventArgs) Handles btnBlack.Click
listbox_add_Black()
End Sub
Private Sub btnBlue_Click(sender As Object, e As EventArgs) Handles btnBlue.Click
listbox_add_Blue()
End Sub
_____________________________________________________________________________________________
Оригинальная версия решения
Я посмотрел на странице справки для поля списка.DrawItem event и внес несколько изменений в
e.Graphics.DrawString
заявление. Кроме того, обратите внимание, что я переместил местоположение
add_item_colour = True
.
Я не стал проверять.
Private Sub listbox_add()
add_item_colour = True
Me.ListBox1.Items.Add(listbox_text(list_num)) ' adds the line to the list box
ListBox1.Refresh()
End Sub
Private Sub ListBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ListBox1.DrawItem
Dim myBrush As Brush = Brushes.Black
e.DrawBackground()
If add_item_colour = True Then
If blue_message = True Then
myBrush = Brushes.Blue
Else
myBrush = Brushes.Black
End If
e.Graphics.DrawString(ListBox1.Items(e.Index).ToString(), e.Font, myBrush, _
e.Bounds, StringFormat.GenericDefault)
add_item_colour = False
End If
e.DrawFocusRectangle()
End Sub
Member 10190163
Спасибо за предложение, но, к сожалению, оно не сработало.
Я получал исключение каждый раз, когда что-то добавлялось: первое случайное исключение типа "система".InvalidOperationException' произошло в системе.Окна.Forms.dll
Кроме того, я видел, как добавлялись некоторые черные и синие элементы, но проблема заключалась в том, что они добавлялись только к первому элементу, а затем они были очищены.
Member 10190163
Я также связал его с этой линией: e.Graphics.Шнурок(Список Listbox1.Предметы.Пункт(list_num).ToString(), e.Font, myBrush, e.Bounds, StringFormat.GenericDefault)
просто на всякий случай это устраняет проблему, когда он добавляется только к первому элементу и очищается, но опять же у меня была та же проблема.
Member 10190163
Кроме того, если вы собираетесь протестировать его, вам нужно не забыть изменить свойство draw mode в списке.
Mike Meinz
См. пересмотренное решение 1. Мне потребовалось две попытки, чтобы получить версию решения, которая работает правильно. Моя первая версия не работала правильно, когда присутствовала вертикальная полоса прокрутки. См. комментарии в решении 1.
Member 10190163
Я использую Windows 7 и Microsoft Visual Basic 2010 Express. Я создал новый проект и попытался применить к нему ваш код. У меня проблема с линией:
e.графика.Шнурок(Список Listbox1.Пользования(по электронной.Индекса).Метод toString(), электронная.Шрифт, arrColors(электронная.Индекс), адрес электронной.Границы, StringFormat.GenericDefault)
Это вызывает исключение, когда нажимается run, и я не могу продолжить работу с программой, потому что она вызывает диалоговое окно, которое позволяет мне тормозить или продолжать, а когда я продолжаю, отладчик останавливается. Сообщения диалогового окна выглядят следующим образом: необработанное исключение типа 'System.Об' произошли в системе.Окна.Forms.dll
Дополнительная информация: InvalidArgument=значение '-1' недопустимо для 'index'.
Mike Meinz
Я изменил ListBox1_DrawItem
в решении 1. Я положил трубку If
заявление по всему миру e.Graphics.DrawString
оператор, чтобы гарантировать, что он выполняется только тогда, когда e.Index > -1
.
Пожалуйста, попробуйте это изменение.
Member 10190163
Это довольно очевидное решение, когда вы смотрите на сообщение об ошибке, я должен был бы это сделать. Спасибо за код, вы мне очень помогли. Я уже проверил это на своей системе, и она хорошо работает. У меня возникли проблемы с реализацией его в моем другом коде, с которым я работал, поскольку синие и черные сообщения кажутся несинхронизированными, это, вероятно, проблема со временем. Но поскольку это отдельный вопрос, то, вероятно, будет лучше, если я открою его как новый вопрос, так что спасибо за вашу помощь, вы решили мою проблему. Ну, во всяком случае, мой первый выпуск.
Mike Meinz
Я не думаю, что время является причиной вашей проблемы.
Mike Meinz
Если вы публикуете эту новую проблему как новый вопрос, пожалуйста, ответьте на это сообщение с URL-адресом нового вопроса.
Member 10190163
Ваше право, это не связано с хронометражем, проблема в том, что позже в моем коде я ограничиваю количество записей listbox этой строкой: Me.ListBox1.Предметы.Remove(listbox_text(0)) ' снять верхнюю запись списка
и это будет означать, что суб ListBox1_DrawItem будет вызван, но новый элемент к нему не добавляется, так что я думаю, что именно поэтому он испортился.
Mike Meinz
Если вы удаляете элементы из списка, то вы должны сделать то же самое изменение в массиве arrColors, который содержит цвета кисти. Массив arrColors должен оставаться синхронизированным со списком. Если вы собираетесь удалять строки из списка, возможно, будет проще использовать коллекцию вместо массива для хранения цветов кисти.
Member 10190163
Хорошо спасибо,
Я увеличил массив до 0 до 550, так как это максимальное значение
и теперь я исправил это с помощью
Для счетчика = от 0 до 549
arrColors(counter) = arrColors(counter + 1)
Следующий
просто до меня.Список listbox1.Предметы.Удалить(listbox_text(0))
линия
Но я не пользовался коллекцией.
Mike Meinz
См. пересмотренное решение 1.
Редакция использует коллекцию и предоставляет listbox_remove_0
для тебя.
Mike Meinz
Я изменил пример в решении 1 так, чтобы он включал в себя listbox_remove_0()
и использует коллекцию вместо массива для сохранения цветов кисти.
Member 10190163
Ой, извините, я не видел этого ответа раньше. Я еще раз взгляну на решение 1.
Mike Meinz
Вот пример ListView, который делает то же самое. Гораздо проще!
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
ListView1.View = View.List
End Sub
Private Sub listview_add(ByVal strText As String, ByVal MyColor As Color)
Dim lstRow As New ListViewItem(strText)
lstRow.ForeColor = MyColor
ListView1.Items.Add(lstRow)
End Sub
Private Sub listview_Remove0()
If ListView1.Items.Count < 1 Then Exit Sub
ListView1.Items.RemoveAt(0)
End Sub
Private Sub btnBlackListView_Click(sender As Object, e As EventArgs) Handles btnBlackListView.Click
listview_add("Black", Color.Black)
End Sub
Private Sub btnBlueListView_Click(sender As Object, e As EventArgs) Handles btnBlueListView.Click
listview_add("Blue", Color.Blue)
End Sub
Private Sub btnRemoveListView_Click(sender As Object, e As EventArgs) Handles btnRemoveListView.Click
listview_Remove0()
End Sub
Member 10190163
Я поместил ваше решение с listbox_remove_0 в проект vb, и оно работает, однако у меня все еще возникают проблемы с синхронизацией, когда я внедряю его в свой другой код. Одна из этих проблем была вызвана тем, что я очистил listbox с помощью listbox1.items.clear (), но теперь я исправил это, очистив коллекцию с помощью colColors.Понятно(). Но у меня все еще есть другие проблемы, потому что он все еще выходит из синхронизации.
Кроме того, я пробовал использовать listview, но он не выполняет того, что я пытаюсь сделать с колонками.
Mike Meinz
Вы должны удалять или добавлять строки в список где-то еще в вашей программе.
Я не понимаю вашего комментария о ListView и столбцах. ListView может создавать столбцы, если для свойства View задано значение View.Details. Когда свойство имеет значение вид.Список, элемент управления ListView ведет себя как элемент управления ListBox (т. е. без колонки). Что вы пытаетесь сделать такого, что, по вашему мнению, ListView не может сделать? Вы тратите много времени, пытаясь заставить ListBox работать, когда ListView должен легко справляться с вашими требованиями.
Member 10190163
Хорошо, теперь я исправил это, это было потому, что я делаю проверку, чтобы увидеть, прерывается ли поток, прежде чем добавить или удалить элемент из списка, но я не делал эту проверку перед добавлением или удалением элемента из коллекции. Теперь это работает.
Однако Спасибо за вашу помощь в этом вопросе.
Mike Meinz
Я все еще удивляюсь, почему вы не можете использовать элемент управления ListView со свойством View, установленным в View.List.
Mike Meinz
Я заметил, что вы еще не приняли решение, так что этот вопрос будет помечен как решенный.