tags:

views:

568

answers:

2

I have databound a listbox to a simple custom object collection. Next, I added a button to remove the selected item from the object collection. The problem is that when certain items are removed and the listbox is showing the vertical scroll bar, the scrollbar appears to reset to a new position, although what I really think is happening is that the control is repainting.

The folowing code sample demonstrates the problem. Add this code to a form, making sure that the vertical scrollbar appears. Select an item in the middle of the collection so that the scrollbar is centered and press the remove button. When the control repaints, the items and scrollbar are in a different position. I would like for the listbox to behave as it would with non-databound items. Am I better off not using databinding, or is there a solution that allows me to keep the contol bound?

Thanks.

public partial class Form1 : Form
{
    private BindingList<ItemData> m_bList = new BindingList<ItemData>();

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        for (int i = 0; i < 50; i++)
        {
            m_bList.Add(new ItemData("Name " + i.ToString(), i)); 
        }
        this.listBox1.DisplayMember = "Name";
        this.listBox1.DataSource = m_bList;
    }

    private void btnRemove_Click(object sender, EventArgs e)
    {
        m_bList.Remove(listBox1.SelectedItem as ItemData);
    }
}

public class ItemData
{
    public string Name { get; set; }
    public int Position { get; set; }

    public ItemData(string name, int position)
    {
        Name = name;
        Position = position;
    }
}
A: 

I can think of one way to dampen the error (note this might not be the most accurate solution) . I just added a few things to the button click event. I am not sure if they solve your requirements completely since you would be the best judge of that, but nonetheless here you go.

 private void btnRemove_Click(object sender, EventArgs e)
    {
        int s = listBox1.SelectedIndex;
        m_bList.Remove(listBox1.SelectedItem as ItemData);
        listBox1.Refresh();
        listBox1.SelectedIndex = s;
     }
bioskope
Just be careful that an item with the old index still exists after you remove the item. For example, if you remove the last item, you will get an IndexOutOfRangeException.
Ty
of course. thanks for pointing that out. I was just trying to provide what might bee called a quick fix to see if that would sort out the issue.
bioskope
I'd change the last line to: listBox1.SelectedIndex = (s >= listBox1.Items.Count) ? listBox1.Items.Count - 1 : s
tsilb
+1  A: 

You need to preserve the TopIndex property of the listbox when removing the item. Preserving SelectedIndex does not stop the scrollbar from jumping. The code below does what I think you want.

    private void btnRemove_Click(object sender,EventArgs e)
    {
        int topIndex = listBox1.TopIndex;

        m_bList.Remove(listBox1.SelectedItem as ItemData);

        if(listBox1.Items.Count>topIndex)
            listBox1.TopIndex = topIndex;
    }
Lee
Thanks Lee! This solves the problem.
You're welcome. Would you mind marking this as the accepted answer?
Lee