【问题标题】:How to refresh DataSource of a ListBox如何刷新列表框的数据源
【发布时间】:2013-07-11 00:07:40
【问题描述】:

Form 有一个 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 中的新选择。我需要将该项目添加到列表中。

我的代码有什么问题?

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    我建议使用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);
        }
    }
    

    动态更改控件数据源有时会产生奇怪的结果。

    【讨论】:

    • 这是最好的方法,因为不会影响选定的值。
    【解决方案2】:

    列表框未检测到您更改了DataSource。只有当Datasource发生变化时才会刷新,所以先将DataSource设置为null:

    listBox1.DataSource = null;
    listBox1.DataSource = data;
    

    您也可以清除项目然后再次设置数据源:

    listBox1.Items.Clear();
    listBox1.DataSource = data;
    

    【讨论】:

    • 在设置 DataSource 属性时无法修改项目集合。所以第二个例子行不通。
    • 注意事项: 设置listBox1.DataSource = null DisplayMember 设置为空字符串(但不是ValueMember)。 (在使用 .NET 4.0 WinForms 的调试器中发现了这一点。)因此,如果您使用的是 DisplayMemberValueMember,请务必在将 DataSource 设置为 null 后重新分配 DisplayMember
    • 使用绑定列表
    【解决方案3】:

    listbox1.DataSource 属性会查找值的变化,但通过始终分配相同的列表,值不会真正改变。

    您可以使用BindingList&lt;T&gt; 而不是List&lt;T&gt; 来自动识别添加的新项目。您的 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);
        }
    }
    

    【讨论】:

    • 只需将listBox1.DataSource = null; 添加为ShowData() 方法的第一行
    • 非常感谢,我花了一个小时试图弄清楚为什么我的列表框无法正确显示我的项目,即使在密切关注微软的教程msdn.microsoft.com/en-us/library/…
    • 哦,这很漂亮。我可以在编辑列表框时使用它来刷新列表框,而不会不必要地弄乱滚动位置。
    • 感谢您的解决方案。
    【解决方案4】:

    另一种可能也是最正确的实现方式是使用提供的ObservableCollection&lt;T&gt;。它的设计目的是实现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&lt;T&gt; 实现了INotifyCollectionChanged,DataSource 绑定将在您的数据更改时自动更新 ListBox。

    【讨论】:

      【解决方案5】:

      在表单初始化时调用 ShowData() 以在初始化时填充您的列表框

       public Department()
              {
                  InitializeComponent();
                  ShowData();
              }
      

      ShowData() 方法,其中设置了BindingSourceDisplayMemberValueMember

      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】:

        也许这个解决方案没有更好的性能,但经过多次尝试和几个小时后,它对我有用:

        这一行是在表单构造函数上执行的:

        listBox1.DataSource = myData;
        
        This lines were executed after the information was modified:
        listBox1.DataSource = new List<Movil>();
        listBox1.DataSource = myData;
        

        希望对你有帮助!

        【讨论】:

          【解决方案7】:

          刷新也可以通过

          listbox.ItemsSource = null;
          listbox.ItemsSource = data;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-01-31
            • 1970-01-01
            • 1970-01-01
            • 2023-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多