[C#.NET][Winform] 利用集合排序,重現 DataGridView 資料繫結後的排序

  • 13256
  • 0
  • 2012-05-09

[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);

會收到例外,看來這招要放棄。

image

2.使用BindingSource.Sort屬性,沒想到它沒反應

 


this._Source.Sort = "Age ASC";
this.dataGridView1.DataSource = this._Source;


BindingSource 無效的話,剩下來只有處理List集合了,處理List集合排序有四個多載方法

image

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

Image result for microsoft+mvp+logo