Как обновить DataSource ListBox
Форма имеет один Combobox и один ListBox. Когда нажимается кнопка "Добавить", я хочу добавить выбранный элемент из ComboBox в ListBox.
public partial class MyForm:Form
{
List<MyData> data = new List<MyData>();
private void ShowData()
{
listBox1.DataSource = data;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
}
private void buttonAddData_Click(object sender, EventArgs e)
{
var selection = (MyData)comboBox1.SelectedItem;
data.Add(selection);
ShowData();
}
}
В этом примере выбранный элемент заменяется новым выбором внутри ListBox. Мне нужно добавить элемент в список.
Что не так с моим кодом?
Ответы
Ответ 1
listbox1.DataSource
ищет изменения значений, но при назначении одного и того же списка все время значение не изменится.
Вы можете использовать BindingList<T>
вместо вашего List<T>
, чтобы автоматически распознавать новые элементы. Метод ShowData() должен быть вызван один раз при запуске.
public partial class MyForm:Form
{
public MyForm(){
InitializeComponent();
ShowData();
}
BindingList<MyData> data = new BindingList<MyData>();
private void ShowData()
{
listBox1.DataSource = data;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
}
private void buttonAddData_Click(object sender, EventArgs e)
{
var selection = (MyData)comboBox1.SelectedItem;
data.Add(selection);
}
}
Ответ 2
Я бы предложил использовать BindingSource
, поскольку он правильно обновил связанные элементы управления.
public partial class MyForm : Form
{
List<MyData> data = new List<MyData>();
BindingSource bs = new BindingSource();
public MyForm()
{
IntializeComponents();
bs.DataSource = data;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
listBox1.DataSource = bs;
}
private void buttonAddData_Click(object sender, EventArgs e)
{
var selection = (MyData)comboBox1.SelectedItem;
data.Add(selection);
bs.ResetBindings(false);
}
}
Изменение источника данных контрольных данных на лету вызывает странный результат.
Ответ 3
В списке не обнаружено, что вы изменили DataSource
. Он будет обновляться только при изменении Datasource
, поэтому сначала установите для DataSource
значение null:
listBox1.DataSource = null;
listBox1.DataSource = data;
Вы также можете очистить элементы, а затем снова установить DataSource:
listBox1.Items.Clear();
listBox1.DataSource = data;
Ответ 4
Альтернативно и, вероятно, наиболее правильным способом реализации этого является использование предоставленного ObservableCollection<T>
. Он разработан с единственной целью реализации INotifyCollectionChanged
.
public partial class MyForm : Form
{
ObservableCollection<MyData> data = new ObservableCollection<MyData>();
public MyForm()
{
listBox1.DataSource = data;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "Id";
}
private void buttonAddData_Click(object sender, EventArgs e)
{
var selection = (MyData)comboBox1.SelectedItem;
data.Add(selection);
}
}
Поскольку ObservableCollection<T>
реализует INotifyCollectionChanged
, привязка DataSource автоматически обновляет ListBox всякий раз, когда ваши данные изменяются.
Ответ 5
Вызвать ShowData()
, когда форма инициализируется для заполнения вашего списка при инициализации
public Department()
{
InitializeComponent();
ShowData();
}
ShowData()
Метод, где BindingSource
, DisplayMember
и ValueMember
установлены
private void ShowData()
{
using (var uow = new UnitOfWork(new SellContext()))
{
listBox1.DataSource = uow.Departments.GetAll().ToList();
listBox1.DisplayMember = "DepartmentName";
listBox1.ValueMember = "DepartmentId";
//listBox1.Invalidate();
}
}
В реализации ниже, когда отдел удаляется из базы данных, список обновляется с текущей коллекцией
private void button1_Click(object sender, EventArgs e)
{
try {
using (var uow = new UnitOfWork(new SellContext()))
{
int count = uow.Departments.FindDepartmentByName(txtDeptName.Text.ToString());
if (count>0)
{
MessageBox.Show("This Department Already Exists", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
else
{
department dept = new department();
dept.DepartmentName = txtDeptName.Text.ToString();
uow.Departments.Create(dept);
if (uow.Complete() > 0)
{
MessageBox.Show("New Department Created", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Information);
txtDeptName.Text = "";
ShowData();
}
else
{
MessageBox.Show("Unable to add Department", "SellRight", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtDeptName.Text = "";
ShowData();
}
}
}
}
catch(Exception ex)
{
ex.ToString();
}
}
Ответ 6
Обновление не приведет к повторному связыванию вашего элемента управления, оно просто приведет к его перерисовке. Если ListBox уже связан с источником данных, вы должны установить источник данных списка как нулевой.
listBox1.DataSource = null;
listBox1.DataSource = DBQuery.informationRetreval().DefaultView;
Он будет обновляться только при изменении объектов, а не данных.
Ответ 7
Возможно, это решение имеет не лучшую производительность, но после многих попыток и нескольких часов оно сработало для меня:
Эта строка была выполнена в конструкторе формы:
listBox1.DataSource = myData;
This lines were executed after the information was modified:
listBox1.DataSource = new List<Movil>();
listBox1.DataSource = myData;
Надеюсь, поможет!