Estoy haciendo un ejemplo para alguien que aún no se dio cuenta de que los controles como ListBox no tiene que contener cadenas; él había sido el almacenamiento de cadenas con formato y saltando a través de complicados análisis de aros para obtener los datos de la ListBox y me gustaría mostrar lo que hay una mejor manera.

Me di cuenta de que si tengo un objeto almacenado en el ListBox, a continuación, actualizar un valor que afecta a ToString, el ListBox no se actualizará. He intentado llamar Refresh y Update en el control, pero ninguno de los dos trabajos. Aquí está el código de ejemplo que estoy usando, ya que requiere que se arrastre un control listbox y un botón en el formulario:

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

Pensé que tal vez el problema fue el uso de los campos y trató de implementar INotifyPropertyChanged, pero esto no tuvo ningún efecto. (La razón por la que estoy usando campos es porque es un ejemplo y no me siento como la adición de una docena de líneas que no tienen nada que ver con el tema que lo estoy demostrando.)

Honestamente nunca he probado la actualización de los elementos en un lugar como este; en el pasado, siempre he sido de agregar/quitar elementos, no la edición de ellos. Así que nunca he notado que no sé cómo hacer este trabajo.

Entonces, ¿qué me estoy perdiendo?

InformationsquelleAutor OwenP | 2008-09-14

10 Comentarios

  1. 24

    BindingList controla la actualización de los enlaces por sí mismo.

    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);
    }
    }
    }
    }
    • Esto es en realidad menos trabajo que las actualmente aceptadas respuesta. Magnífico! He editado tu post para incluir un ejemplo.
    • Se podría mejorar la realidad de que más creo. Usted puede solicitar los padres y el niño enlaces a los controles, lo que significa que usted podría hacer sin la _SelectedIndexChanged controlador de eventos. Se me olvida el preciso aunque el código….. 🙁
    • He actualizado el ejemplo, la eliminación del evento SelectedIndexChanged controlador y reemplazar con 2 nuevas líneas en el controlador Carga. 🙂
    • He estado buscando algo como esto desde hace años. Muchos puntos de karma para ti!
    • Yo estaba usando una Lista, pero no creo que ese era el problema y estaba mirando a todas partes por las molestias. Gracias!
    • Hm, traté de usar esto, pero el ListBox se bloquea continuamente. Parece que es completamente incapaz de manejar los elementos cuya representación en forma de cadena es la cadena vacía. Y eso es un muy grave error.
    • Este ejemplo no funciona para mí, cuadro de lista no muestran valores actualizados (acabo de copiar/pegar el código)… ¿qué está pasando?
    • Por lo que puedo decir, este no aborda la cuestión de la realidad, la actualización del texto de los elementos de la lista.

  2. 33

    Yo uso esta clase cuando siento la necesidad de tener un cuadro de lista que se actualiza.

    Actualizar el objeto en la lista y, a continuación, llamar a cualquiera de los métodos, dependiendo de si usted tiene el índice disponible o no. Si va a actualizar un objeto que está en la lista, pero usted no tiene el índice, usted tendrá que llamar a RefreshItems y la actualización de todos los elementos.

    public class RefreshingListBox : ListBox
    {
    public new void RefreshItem(int index)
    {
    base.RefreshItem(index);
    }
    public new void RefreshItems()
    {
    base.RefreshItems();
    }
    }
    • Nota, RefreshItem sólo funciona si el DisplayMember se establece la propiedad.
  3. 29
    lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem;
    • esta es una respuesta válida, de hecho!
    • Este tiene mi voto! Simple, se puede hacer sin agregar nuevas clases o párrafos de código. Esto era todo lo que necesitaba.
    • Fantástico, sencillo y hace el trabajo, gracias!
    • Tenga en cuenta, que esto no funciona, si establece los elementos a través de la DataSource de la propiedad.
    • Estúpido simple. Gran respuesta.
  4. 16
    typeof(ListBox).InvokeMember("RefreshItems", 
    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
    null, myListBox, new object[] { });
    • He encontrado esta útil: puede utilizarse para hacer que el cuadro de lista para actualizar dinámicamente
  5. 9

    Uso de la propiedad datasource y un objeto BindingSource entre el origen de datos y la propiedad datasource del control listbox. A continuación, la actualización de que.

    actualización ejemplo.

    Así:

    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
    • Excelente. Por alguna razón, el enlace de datos en formularios windows forms nunca salta sobre mí como una solución, no importa cuánto yo lo uso en WPF.
    • Je solía ser incluso más divertido que esto. Algo así como: ((CurrencyManager)este.BindingContext[ListBox1]).Refresh(); Conseguir un «oculto» objeto fuera de la BindingContext y, a continuación, casting para un administrador de moneda. Aunque este es el C# como nunca hice este en VB.NET.
    • Esta es una buena respuesta, pero en última instancia geno sugerencia de uso BindingList<T> conduce a menos trabajo.
  6. 1

    Si deriva de ListBox no es el RefreshItem método protegido puede llamar. Acabo de volver a exponer este método en su propio tipo.

    public class ListBox2 : ListBox {
    public void RefreshItem2(int index) {
    RefreshItem(index);
    }
    }

    A continuación, cambiar su diseñador de archivo a utilizar su propio tipo (en este caso, ListBox2).

  7. 0

    Es poco profesional, pero funciona.
    Me acaba de quitar y se añade el elemento (también seleccionado de nuevo).
    La lista se ordena de acuerdo a «la visualización y cambio de la» propiedad así que, de nuevo, estaba bien para mí. El efecto secundario es que el evento adicional (índice cambiado) es elevada.

    if (objLstTypes.SelectedItem != null)
    {
    PublisherTypeDescriptor objType = (PublisherTypeDescriptor)objLstTypes.SelectedItem;
    objLstTypes.Items.Remove(objType);
    objLstTypes.Items.Add(objType);
    objLstTypes.SelectedItem = objType;
    }
    • ¿por qué bajar votos??
    • Esto será siempre poner el elemento seleccionado al final de la ListBox!
  8. 0

    Si utiliza un método de dibujo como:

    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);
    }

    Sensor es de mi clase.

    Así que si puedo cambiar la clase Color en algún lugar, se puede simplemente actualizar como:

    int temp = listBoxName.SelectedIndex;
    listBoxName.SelectedIndex = -1;
    listBoxName.SelectedIndex = temp;

    Y la Color va a actualizar, solo otra solución 🙂

  9. -1

    No sé mucho acerca de vb.net pero en C# debe utilizar el origen de datos y, a continuación, enlazar llamando a listbox.bind() haría el truco.

    • Eso es para teh internets. A mi entender esta interesado en WinForm.
  10. -3

    Si objLstTypes es su cuadro de lista nombre de
    Uso
    objLstTypes.Elementos.Refresh();
    Espero que esto funcione…

    • No hay ningún método de actualización.

Dejar respuesta

Please enter your comment!
Please enter your name here