Подтвердить что ты не робот

Как сделать 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, но это не имело никакого эффекта. (Причина, по которой я использую поля, - это пример, и мне не хочется добавлять несколько десятков строк, которые не имеют никакого отношения к теме, которую я демонстрирую.)

Честно говоря, я никогда не пробовал обновлять элементы, как раньше; в прошлом я всегда добавлял/удалял элементы, а не редактировал их. Поэтому я никогда не замечал, что я не знаю, как это сделать.

Итак, что мне не хватает?

4b9b3361

Ответ 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(); Надеюсь, это сработает...