ListBox强制更新项目

时间:2014-11-22 11:53:58

标签: c# winforms listbox .net-3.5

我创建了一个ListBoxItem,其中我有一个属性Name并覆盖ToString()以返回名称。当我添加新项目时,这很好用。

但是现在我需要在更改船名时强制ListBox更新标签。我认为刷新或更新会这样做,但那不起作用。

我可能会在这里遗漏一些东西。

public class ShipListBoxItem
{
    public ListBox Parent { get; set; }

    public ShipType Ship { get; set; }

    public ShipListBoxItem()
    {
        Ship = new ShipType();
    }

    public ShipListBoxItem(ShipType st)
    {
        Ship = st;
    }

    public override string ToString()
    {
        return Ship.Name;
    }

    public void UpdateListBox()
    {
        Parent.Refresh(); //My problem is here. Update doesn't work either.
    }

    public static ShipListBoxItem AddToListBox(ListBox lb, ShipType ship)
    {
        ShipListBoxItem li = new ShipListBoxItem(ship);

        li.Parent = lb;

        lb.Items.Add(li);

        return li;
    }
}

3 个答案:

答案 0 :(得分:1)

试试这个

 ListBox.RefreshItems()

msdn

编辑:您可以使用这样的扩展类:

public class FooLisBox : System.Windows.Forms.ListBox
{
    public void RefreshAllItems()
    {
        RefreshItems();
    }
}


private void button1_Click(object sender, EventArgs e)
{
   (listBox1.Items[0] as ShipListBoxItem).Ship.Name = "AAAA";
   listBox1.RefreshAllItems();
}

答案 1 :(得分:1)

如果您使用List<T>作为列表框的DataSource,则很容易对项目进行更改。这也意味着没有真正的理由让我有一个特殊的类来向ListBox添加ShipListBoxItem,你的基本Ship类可以工作:

class ShipItem
{
    public enum ShipTypes { BattleShip, Carrier, Destroyer, Submarine, Frigate };

    public ShipTypes Ship { get; set; }
    public string Name { get; set; }

    public ShipItem(string n, ShipTypes st)
    {
        Name = n;
        Ship = st;
    }

    public override string ToString()
    {
        return String.Format("{0}: {1}", Ship.ToString(), Name);
    }
}

与表单相关的内容:

private void Form1_Load(object sender, EventArgs e)
{
    // add some ships
    Ships = new List<ShipItem>();
    Ships.Add(new ShipItem("USS Missouri", ShipTypes.BattleShip));
    Ships.Add(new ShipItem("USS Ronald Reagan", ShipTypes.Carrier));
    lb.DataSource = Ships;
 }

private void button1_Click(object sender, EventArgs e)
{
    // change a ship name
    lb.DataSource = null;           // suspend binding
    this.Ships[0].Name = "USS Iowa";
    lb.DataSource = Ships;          // rebind
    lb.Refresh();
}

作为替代方案,您还可以使用DisplayMember告诉列表框使用特定属性进行显示:

lb.DataSource = Ships;
lb.DisplayMember = "Name";

这将使用列表框中的Name属性而不是ToString方法。如果您的列表发生了很大变化,请改用BindingList。当你添加它们而不切换DataSource时,它将允许更改列表框中显示的列表。

答案 2 :(得分:0)

我设法解决了我的问题。

大多数情况下,感谢Jose M.

然而,我遇到了一个问题。 RefreshItems()触发OnSelectedIndexChanged()

所以我的被覆盖的类看起来像这样

public class MyListBox : ListBox
{
    public bool DoEvents{ get; set; } // Made it public so in the future I can block event triggering externally

    public MyListBox()
    {
        DoEvents = true;
    }

    public void RefreshAllItems()
    {
        SuspendLayout();
        DoEvents = false;
        base.RefreshItems(); // this triggers OnSelectedIndexChanged as it selects the selected item again
        DoEvents = true;
        ResumeLayout();
    }

    // I only use this event but you can add all events you need to block  
    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        if (DoEvents)
            base.OnSelectedIndexChanged(e);
    }
}