WinForm中ListBox的数据源

我是一向都不喜欢WinForm的ListBox控件,Items中的项没有Tag属性,只好直接使用ListBox的DataSource和DisplayMember属性设定数据源和显示,用起来很不爽。可恶的DataSource不会因为源的改变而重新响应到前台UI,每次不得不通过重新设置DataSource实现刷新UI的效果。下面是一个简单列表框数据源设置示例,直接用csc编译即可。

  1. /* ListBox的数据源
  2. * 编译:csc.exe /target:winexe ListBoxDataSource.cs
  3. */  
  4.   
  5. using System;   
  6. using System.Collections.Generic;   
  7. using System.ComponentModel;   
  8. using System.Drawing;   
  9. using System.Linq;   
  10. using System.Text;   
  11. using System.Windows.Forms;   
  12. using System.Diagnostics;   
  13.   
  14. namespace WindowsFormsApplication1   
  15. {   
  16.     public partial class Form1 : Form   
  17.      {   
  18.         /// <summary>   
  19.         /// 声明将来作为ListBox数据的类型   
  20.         /// </summary>   
  21.         struct MyData   
  22.          {   
  23.             public Guid Id { get; set; }        //数据必须采用公开属性   
  24.             public string Name { get; set; }   
  25.          }   
  26.   
  27.          List<MyData> m_SourceList;      //源ListBox的数据源对象   
  28.          List<MyData> m_DestinationList; //目的ListBox的数据源对象   
  29.         static readonly int m_Capacity = 10;    //列表容量   
  30.   
  31.         //构造   
  32.         public Form1()   
  33.          {   
  34.              InitializeComponent();   
  35.              m_SourceList = new List<MyData>(m_Capacity);   
  36.              m_DestinationList = new List<MyData>(m_Capacity);   
  37.              KeyPreview = true;   
  38.          }   
  39.   
  40.         /// <summary>   
  41.         /// 初始化数据   
  42.         /// </summary>   
  43.         private void InitData()   
  44.          {   
  45.              m_SourceList.Clear();   
  46.              m_DestinationList.Clear();   
  47.              m_SourceList.Capacity = m_DestinationList.Capacity = m_Capacity;   
  48.             for (int i = 0; i < m_Capacity; i++)   
  49.              {   
  50.                  var data = new MyData()   
  51.                  {   
  52.                      Id = Guid.NewGuid(),   
  53.                      Name = string.Format("the {0} of hearts", i == 0 ? "ace" : (i + 1).ToString())   
  54.                  };   
  55.                  m_SourceList.Add(data);   
  56.              }   
  57.          }   
  58.   
  59.         /// <summary>   
  60.         /// 初始化UI   
  61.         /// </summary>   
  62.         private void InitUI()   
  63.          {   
  64.              listBox1.DataSource = null;   
  65.              listBox1.DisplayMember = null;   
  66.              listBox2.DataSource = null;   
  67.              listBox2.DisplayMember = null;   
  68.              InitData();   
  69.              RefreshUI();   
  70.          }   
  71.   
  72.         /// <summary>   
  73.         /// 刷新UI   
  74.         /// </summary>   
  75.         private void RefreshUI()   
  76.          {   
  77.             //重新设置数据源   
  78.              listBox1.DataSource = m_SourceList;   
  79.              listBox1.DisplayMember = "Name";   
  80.              listBox2.DataSource = m_DestinationList;   
  81.              listBox2.DisplayMember = "Name";   
  82.          }   
  83.   
  84.         /// <summary>   
  85.         /// 重写窗口OnLoad方法   
  86.         /// </summary>   
  87.         /// <param name="e"></param>   
  88.         protected override void OnLoad(EventArgs e)   
  89.          {   
  90.              InitUI();   
  91.             base.OnLoad(e);   
  92.          }   
  93.   
  94.         //“>”   
  95.         private void button1_Click(object sender, EventArgs e)   
  96.          {   
  97.              var selecteditems = listBox1.SelectedItems;   
  98.             if (selecteditems.Count == 0) return;   
  99.              var tmpList = new List<MyData>(selecteditems.Count);   
  100.             foreach (MyData item in selecteditems) tmpList.Add(item);   
  101.              m_SourceList = m_SourceList.Except(tmpList).ToList();   
  102.              m_DestinationList = m_DestinationList.Union(tmpList).ToList();   
  103.              RefreshUI();   
  104.          }   
  105.   
  106.         //“<”   
  107.         private void button2_Click(object sender, EventArgs e)   
  108.          {   
  109.              var selecteditems = listBox2.SelectedItems;   
  110.             if (selecteditems.Count == 0) return;   
  111.              var tmpList = new List<MyData>(selecteditems.Count);   
  112.             foreach (MyData item in selecteditems) tmpList.Add(item);   
  113.              m_SourceList = m_SourceList.Union(tmpList).ToList();   
  114.              m_DestinationList = m_DestinationList.Except(tmpList).ToList();   
  115.              RefreshUI();   
  116.          }   
  117.   
  118.         //“>>”   
  119.         private void button3_Click(object sender, EventArgs e)   
  120.          {   
  121.              var items = listBox1.Items;   
  122.             if (items.Count == 0) return;   
  123.              var tmpList = new List<MyData>(items.Count);   
  124.             foreach (MyData item in items) tmpList.Add(item);   
  125.              m_SourceList = m_SourceList.Except(tmpList).ToList();   
  126.              m_DestinationList = m_DestinationList.Union(tmpList).ToList();   
  127.              RefreshUI();   
  128.          }   
  129.   
  130.         //“<<”   
  131.         private void button4_Click(object sender, EventArgs e)   
  132.          {   
  133.              var items = listBox2.Items;   
  134.             if (items.Count == 0) return;   
  135.              var tmpList = new List<MyData>(items.Count);   
  136.             foreach (MyData item in items) tmpList.Add(item);   
  137.              m_SourceList = m_SourceList.Union(tmpList).ToList();   
  138.              m_DestinationList = m_DestinationList.Except(tmpList).ToList();   
  139.              RefreshUI();   
  140.          }
  141.          (略……)   
  142.      }
  143.      #region 入口点   
  144.     static class Program   
  145.      {   
  146.         /// <summary>   
  147.         /// 应用程序的主入口点。   
  148.         /// </summary>   
  149.          [STAThread]   
  150.         static void Main()   
  151.          {   
  152.              Application.Run(new Form1());   
  153.          }   
  154.      }
  155.      #endregion   
  156. }   

需要注意的是,使用DataSource“刷新”数据的时候,如果重新指定DataSource的引用与原来的引用是同一个,那么控件是不会重新读取数据进行刷新的。这一点很重要,因此只能重新设定DataSource时才有效,判断是否重新设定了DataSource,可以在其后读取DisplayMember或者ValueMember属性,它们会被置为空串,这意味着你需要再重新设定DisplayMember属性和ValueMember属性。如代码中62行的InitUI方法,它总是先设置DataSource=null再调用RefreshUI方法重新指定DataSource。代码75行的RefreshUI方法实际上是个败笔,因为仅仅是它并不能总会正确地实现“刷新UI”的效果,先将DataSource指向null是必要的。但为什么这段程序能够正确执行?95行到140行的代码中,所有对数据源m_SourceList或者m_DestinationList的操作采用的集合运算Except方法和Union方法,最终会产生一组新的集合,也就是说m_SourceList和m_DestinationList的引用已经是新的,所以RefreshUI方法中DataSource会生效,数据被正确绘制出来。

2009年6月11日12时17分05秒 补充

上面代码中有一个非常致命的错误。我用List<T>来作数据源,所以ListBox并不能够自动根据源的改变而正确响应。作为“列表”的数据源绑定,.NET 2.0中有一个。用csc编译下面的程序:

  1. using System;   
  2. using System.Windows.Forms;   
  3. using System.Drawing;   
  4. using System.ComponentModel;   
  5.   
  6. namespace ListBoxDataSource2   
  7. {   
  8.     static class Program   
  9.      {   
  10.          [STAThread]   
  11.         static void Main()   
  12.          {   
  13.              var blist = new BindingList<mydata>();  //声明一个用于绑定的BindingList<T>泛型对象   
  14.              var f = new Form()  //主窗口   
  15.              {   
  16.                  Text = "列表框的数据绑定2   F1 - 博客",   
  17.                  Size = new Size(200, 300),   
  18.                  KeyPreview = true  
  19.              };   
  20.              var listbox = new ListBox() //列表框   
  21.              {   
  22.                  Location = new Point(10, 10),   
  23.                  Size = new Size(f.Width - 30, f.Height - 100),   
  24.                  DataSource = blist,     //设置列表框的数据源为blist   
  25.                  DisplayMember = "Text", //设置显示成员为blist.Text   
  26.                  Parent = f   
  27.              };   
  28.              var buttonAdd = new Button() //添加按钮   
  29.              {   
  30.                  Text = "Add",   
  31.                  Location = new Point(10, f.Height - 75),   
  32.                  Parent = f   
  33.              };   
  34.              var buttonRemove = new Button() //删除按钮   
  35.              {   
  36.                  Text = "Remove",   
  37.                  Location = new Point(110, f.Height - 75),   
  38.                  Parent = f   
  39.              };   
  40.              buttonAdd.Click += delegate //添加按钮的单击事件   
  41.              {   
  42.                  blist.Add(new mydata()   
  43.                  {   
  44.                      Text = System.IO.Path.GetRandomFileName(),   
  45.                      Time = DateTime.Now   
  46.                  });   
  47.              };   
  48.              buttonRemove.Click += delegate //删除按钮的单击事件   
  49.              {   
  50.                 if (listbox.SelectedItem != null)   
  51.                  {   
  52.                      var selected = (mydata)listbox.SelectedItem;   
  53.                      blist.Remove(selected);   
  54.                  }   
  55.              };   
  56.              f.KeyUp += delegate(object sernder, KeyEventArgs e)   
  57.              {   
  58.                 if (Keys.F1 == e.KeyCode)   
  59.                  {   
  60.                      System.Diagnostics.Process.Start("http://hi.baidu.com/wingingbob/blog/item/7c2ffb343f026dbfd0a2d391.html");   
  61.                  }   
  62.              };   
  63.              Application.Run(f);   
  64.          }   
  65.   
  66.         struct mydata   //我的数据类型   
  67.          {   
  68.             public string Text { get; set; }   
  69.             public DateTime Time { get; set; }   
  70.          }   
  71.      }   
  72. }   
http://hi.baidu.com/wingingbob/item/1c445f09c11ab2dd73e6765b
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在WinForm,您可以将ListBox控件绑定到List类型的数据源。为此,您需要将List数据源设置为ListBoxDataSource属性,然后设置ListBox的DisplayMember属性为您希望显示的数据源对象的属性名称。 例如,如果您有一个List<Student>类型的数据源,其Student对象具有Name和Age属性,您可以将ListBox控件绑定到该数据源,并设置DisplayMember属性为"Name",这样ListBox将显示所有学生的名称。 ### 回答2: 在WinFormsListBox控件可以通过绑定List类型的数据源来显示数据,并使用DisplayMember属性来指定要显示的成员属性。 首先,我们需要创建一个List类型的数据源。假设我们有一个名为Student的类,其包含Name和Age两个属性: ```csharp public class Student { public string Name { get; set; } public int Age { get; set; } } ``` 然后,我们可以创建一个List<Student>对象,并添加一些数据: ```csharp List<Student> students = new List<Student>(); students.Add(new Student { Name = "张三", Age = 20 }); students.Add(new Student { Name = "李四", Age = 21 }); students.Add(new Student { Name = "王五", Age = 22 }); ``` 接下来,我们需要将ListBox控件与数据源绑定,并设置DisplayMember属性。在设计界面上,找到ListBox控件的属性窗口,展开数据部分,将数据源DataSource)设置为我们创建的List<Student>对象,将显示成员(DisplayMember)设置为要显示的属性名称(例如,Name)。 如果希望以另一种格式显示每个项,可以使用格式化字符串。在DisplayMember属性,可以指定一个格式化字符串,其可以包含属性名称以及其他文本。 ```csharp listBox1.DataSource = students; listBox1.DisplayMember = "Name"; ``` 最后,运行程序,ListBox控件就会显示我们绑定的List<Student>对象的Name属性值。每个项将按照DisplayMember属性指定的方式进行显示。 通过这种方式,我们可以方便地将List类型的数据源绑定到ListBox控件,并根据需要定制显示方式。 ### 回答3: 在WinForm,我们可以使用ListBox控件来展示列表类型的数据源,并通过设置DisplayMember属性来指定要在列表显示的字段。 要绑定list类型的数据源,首先我们需要创建一个List<T>对象,其的T可以是任何我们想要展示的类型。例如,我们想要展示一个包含学生姓名的列表,我们可以创建一个List<string>对象。 然后,我们可以通过将这个List<string>对象赋值给ListBox控件的DataSource属性来将数据源与控件进行绑定。这将使ListBox控件显示列表的所有项目。 接下来,我们需要设置DisplayMember属性来确定要在列表显示的字段。对于List<string>对象,由于它只包含一个字段(学生姓名),我们可以将DisplayMember属性设置为"Item",这将使ListBox控件在列表显示学生姓名。 在代码,我们可以这样做: ```c# List<string> studentList = new List<string>(); // 创建List<string>对象 studentList.Add("张三"); studentList.Add("李四"); studentList.Add("王五"); listBox1.DataSource = studentList; // 将数据源ListBox控件绑定 listBox1.DisplayMember = "Item"; // 设置要显示的字段为"Item" ``` 这样,当我们运行程序时,ListBox控件将显示一个包含所有学生姓名的列表,每个学生姓名都作为一个项目显示。 总而言之,通过将List类型的数据源赋值给ListBox控件的DataSource属性,并设置DisplayMember属性来确定要在列表显示的字段,我们可以在WinForm使用ListBox控件展示列表类型数据源

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值