45 votes

Comment puis-je faire une ListBox actualiser son texte d'un élément?

Je suis en train de faire un exemple pour quelqu'un qui n'a pas encore réalisé que les commandes comme ListBox n'ont pas à contenir des chaînes; il avait été le stockage formaté de cordes et de sauter à travers compliqué l'analyse des cerceaux pour obtenir les données de retour de l' ListBox et j'aimerais lui montrer il ya une meilleure façon.

J'ai remarqué que si j'ai un objet stocké dans l' ListBox puis de mettre à jour une valeur qui affecte ToString, l' ListBox ne met pas à jour lui-même. J'ai essayé de les appeler, Refresh et Update sur le contrôle, mais aucun ne fonctionne. Voici le code de l'exemple que j'utilise, cela nécessite que vous faites glisser un contrôle listbox et un bouton sur le formulaire:

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

J'ai pensé que peut-être que le problème a été en utilisant les champs et essayé de la mise en œuvre de INotifyPropertyChanged, mais cela n'a eu aucun effet. (La raison pour laquelle je suis à l'aide de champs, parce que c'est un exemple et je n'ai pas envie d'ajouter quelques dizaines de lignes qui n'ont rien à voir avec le sujet je suis à la démonstration.)

Honnêtement, je n'ai jamais essayé la mise à jour des articles dans ce genre d'endroit avant; dans le passé, j'ai toujours été l'ajout/suppression d'éléments, ne pas les modifier. Donc, je n'ai jamais remarqué que je ne sais pas comment faire ce travail.

Donc ce qui me manque?

35voto

Brad Bruce Points 4359

J'utilise cette classe lorsque j'ai besoin d'avoir une zone de liste que les mises à jour.

Mise à jour de l'objet dans la liste et ensuite appeler les méthodes, en fonction de si vous avez l'indice est disponible ou non. Si vous êtes à la mise à jour d'un objet qui est contenue dans la liste, mais vous n'avez pas l'index, vous devrez appeler RefreshItems et mise à jour de tous les éléments.

public class RefreshingListBox : ListBox
{
    public new void RefreshItem(int index)
    {
        base.RefreshItem(index);
    }

    public new void RefreshItems()
    {
        base.RefreshItems();
    }
}

30voto

Elton M Points 71
lstBox.Items[lstBox.SelectedIndex] = lstBox.SelectedItem;

25voto

geno Points 224

BindingList gère la mise à jour les liaisons par lui-même.

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

16voto

Jon Points 141
typeof(ListBox).InvokeMember("RefreshItems", 
  BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
  null, myListBox, new object[] { });

10voto

Quibblesome Points 14441

Utilisez la propriété source de données et un BindingSource objet entre la source de données et la propriété datasource du contrôle listbox. Puis actualisez cette.

mise à jour ajout d'un exemple.

Comme suit:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X