У меня есть привязка списка к простой коллекции настраиваемых объектов. Затем я добавил кнопку для удаления выбранного элемента из коллекции объектов. Проблема в том, что когда определенные элементы удаляются и в списке отображается вертикальная полоса прокрутки, полоса прокрутки сбрасывается в новое положение, хотя я действительно думаю, что происходит перерисовка элемента управления.
Следующий пример кода демонстрирует проблему. Добавьте этот код в форму, убедившись, что отображается вертикальная полоса прокрутки. Выберите элемент в середине коллекции, чтобы полоса прокрутки была по центру, и нажмите кнопку удаления. Когда элемент управления перерисовывается, элементы и полоса прокрутки находятся в другом положении. Я хотел бы, чтобы список вёл себя так же, как и с элементами, не связанными с данными. Мне лучше не использовать привязку данных, или есть решение, которое позволяет мне сохранить привязку к контролю?
Спасибо.
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;
}
}





Я могу придумать один способ смягчить ошибку (обратите внимание, что это может быть не самое точное решение). Я просто добавил несколько вещей в событие нажатия кнопки. Я не уверен, полностью ли они решают ваши требования, поскольку вы будете лучшим судьей в этом, но, тем не менее, готово.
private void btnRemove_Click(object sender, EventArgs e)
{
int s = listBox1.SelectedIndex;
m_bList.Remove(listBox1.SelectedItem as ItemData);
listBox1.Refresh();
listBox1.SelectedIndex = s;
}
конечно. Спасибо что подметил это. Я просто пытался предоставить то, что можно было бы назвать быстрым решением, чтобы посмотреть, решит ли это проблему.
Я бы изменил последнюю строку на: listBox1.SelectedIndex = (s> = listBox1.Items.Count)? listBox1.Items.Count - 1: s
При удалении элемента вам необходимо сохранить свойство TopIndex списка. Сохранение SelectedIndex не мешает полосе прокрутки прыгать. Приведенный ниже код делает то, что я думаю, вам нужно.
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;
}
Просто будьте осторожны, чтобы элемент со старым индексом все еще существовал после удаления элемента. Например, если вы удалите последний элемент, вы получите исключение IndexOutOfRangeException.