Как сделать ListBox обновить текст элемента?
Я делаю пример для тех, кто еще не понял, что элементы управления, такие как ListBox
, не должны содержать строки; он сохранял форматированные строки и прыгал через сложные синтаксические обручи, чтобы вернуть данные из ListBox
, и я хотел бы показать ему лучший способ.
Я заметил, что если у меня есть объект, хранящийся в ListBox
, то обновить значение, которое влияет на ToString
, ListBox
не обновляется. Я пробовал называть Refresh
и Update
в элементе управления, но не работает. Здесь код примера, который я использую, он требует перетащить список и кнопку на форму:
Public Class Form1
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
For i As Integer = 1 To 3
Dim tempInfo As New NumberInfo()
tempInfo.Count = i
tempInfo.Number = i * 100
ListBox1.Items.Add(tempInfo)
Next
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each objItem As Object In ListBox1.Items
Dim info As NumberInfo = DirectCast(objItem, NumberInfo)
info.Count += 1
Next
End Sub
End Class
Public Class NumberInfo
Public Count As Integer
Public Number As Integer
Public Overrides Function ToString() As String
Return String.Format("{0}, {1}", Count, Number)
End Function
End Class
Я думал, что, возможно, проблема заключалась в использовании полей и попытке реализации INotifyPropertyChanged, но это не имело никакого эффекта. (Причина, по которой я использую поля, - это пример, и мне не хочется добавлять несколько десятков строк, которые не имеют никакого отношения к теме, которую я демонстрирую.)
Честно говоря, я никогда не пробовал обновлять элементы, как раньше; в прошлом я всегда добавлял/удалял элементы, а не редактировал их. Поэтому я никогда не замечал, что я не знаю, как это сделать.
Итак, что мне не хватает?
Ответы
Ответ 1
BindingList обрабатывает сами привязки.
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace TestBindingList
{
public class Employee
{
public string Name { get; set; }
public int Id { get; set; }
}
public partial class Form1 : Form
{
private BindingList<Employee> _employees;
private ListBox lstEmployees;
private TextBox txtId;
private TextBox txtName;
private Button btnRemove;
public Form1()
{
InitializeComponent();
FlowLayoutPanel layout = new FlowLayoutPanel();
layout.Dock = DockStyle.Fill;
Controls.Add(layout);
lstEmployees = new ListBox();
layout.Controls.Add(lstEmployees);
txtId = new TextBox();
layout.Controls.Add(txtId);
txtName = new TextBox();
layout.Controls.Add(txtName);
btnRemove = new Button();
btnRemove.Click += btnRemove_Click;
btnRemove.Text = "Remove";
layout.Controls.Add(btnRemove);
Load+=new EventHandler(Form1_Load);
}
private void Form1_Load(object sender, EventArgs e)
{
_employees = new BindingList<Employee>();
for (int i = 0; i < 10; i++)
{
_employees.Add(new Employee() { Id = i, Name = "Employee " + i.ToString() });
}
lstEmployees.DisplayMember = "Name";
lstEmployees.DataSource = _employees;
txtId.DataBindings.Add("Text", _employees, "Id");
txtName.DataBindings.Add("Text", _employees, "Name");
}
private void btnRemove_Click(object sender, EventArgs e)
{
Employee selectedEmployee = (Employee)lstEmployees.SelectedItem;
if (selectedEmployee != null)
{
_employees.Remove(selectedEmployee);
}
}
}
}
Ответ 2
Я использую этот класс, когда мне нужно обновить список.
Обновите объект в списке, а затем вызовите любой из включенных методов, в зависимости от того, доступен ли этот индекс или нет. Если вы обновляете объект, который содержится в списке, но у вас нет индекса, вам нужно будет вызвать RefreshItems и обновить все элементы.
public class RefreshingListBox : ListBox
{
public new void RefreshItem(int index)
{
base.RefreshItem(index);
}
public new void RefreshItems()
{
base.RefreshItems();
}
}
Ответ 3
lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem;
Ответ 4
typeof(ListBox).InvokeMember("RefreshItems",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
null, myListBox, new object[] { });
Ответ 5
Используйте свойство datasource и объект BindingSource между источником данных и свойством datasource в списке. Затем обновите это.
обновить добавленный пример.
Так же:
Public Class Form1
Private datasource As New List(Of NumberInfo)
Private bindingSource As New BindingSource
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
For i As Integer = 1 To 3
Dim tempInfo As New NumberInfo()
tempInfo.Count = i
tempInfo.Number = i * 100
datasource.Add(tempInfo)
Next
bindingSource.DataSource = datasource
ListBox1.DataSource = bindingSource
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each objItem As Object In datasource
Dim info As NumberInfo = DirectCast(objItem, NumberInfo)
info.Count += 1
Next
bindingSource.ResetBindings(False)
End Sub
End Class
Public Class NumberInfo
Public Count As Integer
Public Number As Integer
Public Overrides Function ToString() As String
Return String.Format("{0}, {1}", Count, Number)
End Function
End Class
Ответ 6
Если вы вышли из ListBox, вы можете вызвать метод RefreshItem protected. Просто повторите этот метод в своем собственном типе.
public class ListBox2 : ListBox {
public void RefreshItem2(int index) {
RefreshItem(index);
}
}
Затем измените свой файл конструктора, чтобы использовать свой собственный тип (в данном случае ListBox2).
Ответ 7
Это немного непрофессионально, но это работает.
Я просто удалил и добавил элемент (также его снова выбрал).
Список был отсортирован в соответствии с "отображаемым и измененным" свойством, поэтому, опять же, это было хорошо для меня. Побочным эффектом является то, что добавляется дополнительное событие (индекс изменен).
if (objLstTypes.SelectedItem != null)
{
PublisherTypeDescriptor objType = (PublisherTypeDescriptor)objLstTypes.SelectedItem;
objLstTypes.Items.Remove(objType);
objLstTypes.Items.Add(objType);
objLstTypes.SelectedItem = objType;
}
Ответ 8
Если вы используете метод draw, например:
private void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
Sensor toBeDrawn = (listBox1.Items[e.Index] as Sensor);
e.Graphics.FillRectangle(new SolidBrush(toBeDrawn.ItemColor), e.Bounds);
e.Graphics.DrawString(toBeDrawn.sensorName, new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold), new SolidBrush(Color.White),e.Bounds);
}
Датчик - это мой класс.
Итак, если я где-то меняю класс Color
, вы можете просто обновить его как:
int temp = listBoxName.SelectedIndex;
listBoxName.SelectedIndex = -1;
listBoxName.SelectedIndex = temp;
И Color
будет обновляться, просто другое решение:)
Ответ 9
Я ничего не знаю о vb.net, но на С# вы должны использовать источник данных, а затем привязать его, вызвав listbox.bind()
, чтобы сделать трюк.
Ответ 10
Если objLstTypes - это ваше имя ListBox
использование
objLstTypes.Items.Refresh();
Надеюсь, это сработает...