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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值