[C#.NET][Winform] 利用集合排序,重現 DataGridView 資料繫結後的排序
我的結構長這樣
public class MemberList
{
private List<Member> _MemberCollection = null;
public List<Member> MemberCollection
{
get
{
if (this._MemberCollection == null)
this._MemberCollection = new List<Member>();
return this._MemberCollection;
}
}
}
public class Member : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private int? _ID;
public int? ID
{
get { return this._ID; }
set
{
this._ID = value;
OnPropertyChanged("ID");
}
}
private string _Name;
public string Name
{
get { return this._Name; }
set
{
this._Name = value;
OnPropertyChanged("Name");
}
}
private int? _Age;
public int? Age
{
get { return this._Age; }
set
{
this._Age = value;
OnPropertyChanged("Age");
}
}
private string _Phone;
public string Phone
{
get { return this._Phone; }
set
{
this._Phone = value;
OnPropertyChanged("Phone");
}
}
}
在主程式裡呼叫
BindingSource _Source = new BindingSource();
List<Member> _List = null;
private void Form1_Load(object sender, EventArgs e)
{
this._List = CreateClass().MemberCollection;
this._Source.DataSource = _List;
this.dataGridView1.DataSource = this._Source;
}
public MemberList CreateClass()
{
MemberList list = new MemberList();
list.MemberCollection.Add(new Member() { ID = 1, Name = "余小章", Age = 18, Phone = "000" });
list.MemberCollection.Add(new Member() { ID = 2, Name = "王小華", Age = 28, Phone = "001" });
list.MemberCollection.Add(new Member() { ID = 3, Name = "張小明", Age = 20, Phone = "002" });
return list;
}
好了!我們都知道原本的dataGridView在沒有資料繫結(Data Binding)之前,按下ColumnHeader後可以進行資料排序,資料繫結後不能排序了,於是我試著使用下列幾種方式來嘗試
1.使用 DataGridView.Sort 方法
this.dataGridView1.Sort(this.dataGridView1.Columns[0], ListSortDirection.Ascending);
會收到例外,看來這招要放棄。
2.使用BindingSource.Sort屬性,沒想到它沒反應
this._Source.Sort = "Age ASC";
this.dataGridView1.DataSource = this._Source;
BindingSource 無效的話,剩下來只有處理List集合了,處理List集合排序有四個多載方法
3.先來看看,使用 Comparison 類別來處理
首先,先寫個MemberComparison類別,裡面有以下靜態方法
class MemberComparison
{
public static int Name(Member x, Member y)
{
return System.Collections.Comparer.Default.Compare(x.Name, y.Name);
}
public static int Phone(Member x, Member y)
{
return System.Collections.Comparer.Default.Compare(x.Phone, y.Phone);
}
public static int Age(Member x, Member y)
{
return (int)x.Age - (int)y.Age;
}
public static int ID(Member x, Member y)
{
return (int)x.ID - (int)y.ID;
}
}
在用戶端裡呼叫new Comparison<Member>(MemberComparison.Age),進行年齡排序
private void button1_Click(object sender, EventArgs e)
{
System.Comparison<Member> NameComparison = new Comparison<Member>(MemberComparison.Age);
this._List.Sort(NameComparison);
this._Source.DataSource = _List;
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this._Source;
}
4.使用IComparer<>泛型,在增加以下類別,每一類別都繼承 IComparer<Member>
class AgeComparer : IComparer<Member>
{
public static AgeComparer Default = new AgeComparer();
public int Compare(Member x, Member y)
{
return (int)x.Age - (int)y.Age;
}
}
public class NameComparer : IComparer<Member>
{
public static NameComparer Default = new NameComparer();
public int Compare(Member x, Member y)
{
return System.Collections.Comparer.Default.Compare(x.Name, y.Name);
}
}
public class IDComparer : IComparer<Member>
{
public static IDComparer Default = new IDComparer();
public int Compare(Member x, Member y)
{
return System.Collections.Comparer.Default.Compare(x.Phone, y.Phone);
}
}
public class PhoneComparer : IComparer<Member>
{
public static PhoneComparer Default = new PhoneComparer();
public int Compare(Member x, Member y)
{
return System.Collections.Comparer.Default.Compare(x.Phone, y.Phone);
}
}
然後在用戶端理呼叫NameComparer.Default,進行名字排序
private void button1_Click(object sender, EventArgs e)
{
this._List.Sort(NameComparer.Default);
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this._Source;
}
5.這樣的寫法或許你覺得太煩了,沒關係我們還有LINQ,寫法可以更精簡
寫法一:
var query = from data in this._List
orderby data.Name
select data;
寫法二:
query = this._List.OrderBy(o => o.Name);
把最後排好的結果轉回List<>再重新繫結一次
List<Member> list = query.ToList<Member>();
this._Source.DataSource = list;
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this._Source;
處理好排序的類別後,選定一種排序方法,處理 ColumnHeaderMouseClick 事件,如此一來就可以找回失落 DataGridView 的排序。
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
DataGridView view = (DataGridView)sender;
BindingSource source = (BindingSource)view.DataSource;
List<Member> list = (List<Member>)source.DataSource;
string columnsName = view.Columns[e.ColumnIndex].HeaderText;
IEnumerable<Member> query = null;
switch (columnsName)
{
case "ID":
query = list.OrderBy(o => o.ID);
break;
case "Name":
query = list.OrderBy(o => o.Name);
break;
case "Age":
query = list.OrderBy(o => o.Age);
break;
case "Phone":
query = list.OrderBy(o => o.Phone);
break;
}
if (query == null)
return;
this._Source.DataSource = query.ToList<Member>();
this.dataGridView1.DataSource = null;
this.dataGridView1.DataSource = this._Source;
}
範例下載:ListSort.zip
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET