簡體   English   中英

C#:自定義DataGridView

[英]C#: Custom sort of DataGridView

我需要使用自然排序(在資源管理器中)對DataGridView進行排序,以便數字和文本(在同一列中)自然排序,而不是按字母順序排序(以便“位置3”位於“位置20”之前,等等)。 我有一個DataGridView,我將DataView設置為DataSource。 DataView包含一個DataTable,它是使用數據庫中的某些值創建的。 列類型是字符串。 我有一個IComparer,它做了它應該做的,但我無法弄清楚如何使用它,因為我無法找到如何進行排序。 DataGridView.SortCompare事件是完美的 ,因為它是數據綁定的,所以不起作用。 DataView.Sort只接受具有列名和排序順序的字符串。

很煩人。 試圖在StackOverflow上閱讀相關問題,並搜索谷歌的很多和很多,但我真的找不到這個。 只有我真正找到的東西是使用dataview的Sort(字符串)方法,因為它按字母順序排序。

有沒有人知道如何做到這一點沒有太多麻煩? 它應該是別人而不是我這個? 我真的不想重新實現整個datagridview或dataview類,只是為了獲得自定義排序...

更新 :如果有人想知道,我仍然在尋找這個問題的好答案。 雖然與此同時,我最終創建了自己的簡單表類,然后手動將其提供給datagridview。 覆蓋SortCompare方法。 有點煩人,但並不太難,因為我只需要顯示值(沒有編輯或任何東西),因此可以將所有內容轉換為字符串。

看看這個MSDN頁面這篇博客文章 原則上,您需要在GridView上配置數據源(無論是ObjectDataSource還是SqlDataSource)的排序。

據我所知,DataView類除了簡單的升序/降序排序外不支持任何其他內容。 如果沒有看到加載和綁定數據的代碼,很難做出具體的推薦,但你可以:

  1. 將數據加載到List而不是DataTable中,調用Sort方法傳遞比較方法,然后綁定到該列表。
  2. 在您的aspx代碼中創建一個ObjectDataSource,直接從類中獲取數據,並配置該ObjectDataSource以使用您的IComparer。

這段代碼應該有效。 它類似於ListView的ListViewItemSorter。 使用IComparer。

使用:

private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    MyDataGridHelper.DataGridSort(dgv, e.ColumnIndex);
}

MyDataGridHelper.cs:

public class MyDataGridHelper
{
    public static void DataGridSort(DataGridView dgv, int column)
    {
        DataGridViewCustomSorter dgvSorter = null;
        if (dgv.Tag == null || !(dgv.Tag is IComparer))
        {
            dgvSorter = new DataGridViewCustomSorter(dgv);
            dgv.Tag = dgvSorter;
        }
        else
        {
            dgvSorter = (DataGridViewCustomSorter)dgv.Tag;
        }
        dgvSorter.SortColumn = column;
        dgv.Sort(dgvSorter);
    }

    private class DataGridViewCustomSorter : IComparer
    {
        private int ColumnIndex;
        private SortOrder OrderOfSort;
        private DataGridView myDataGridView;
        private TypeCode mySortTypeCode;

        public DataGridViewCustomSorter(DataGridView dgv)
        {
            myDataGridView = dgv;
            mySortTypeCode = Type.GetTypeCode(Type.GetType("System.String"));
            ColumnIndex = 0;
            OrderOfSort = SortOrder.None;
        }

        public int Compare(object x, object y)
        {
            int result;
            DataGridViewRow dgvX, dgvY;

            dgvX = (DataGridViewRow)x;
            dgvY = (DataGridViewRow)y;
            string sx = dgvX.Cells[ColumnIndex].Value.ToString();
            string sy = dgvY.Cells[ColumnIndex].Value.ToString();

            //null handling
            if (sx == String.Empty && sy == String.Empty)
                result = 0;
            else if (sx == String.Empty && sy != String.Empty)
                result = -1;
            else if (sx != String.Empty && sy == String.Empty)
                result = 1;
            else
            {
                switch (mySortTypeCode)
                {
                    case TypeCode.Decimal:
                        Decimal nx = Convert.ToDecimal(sx);
                        Decimal ny = Convert.ToDecimal(sy);
                        result = nx.CompareTo(ny);
                        break;
                    case TypeCode.DateTime:
                        DateTime dx = Convert.ToDateTime(sx);
                        DateTime dy = Convert.ToDateTime(sy);
                        result = dx.CompareTo(dy);
                        break;
                    case TypeCode.String:
                        result = (new CaseInsensitiveComparer()).Compare(sx, sy);
                        break;
                    default:
                        result = (new CaseInsensitiveComparer()).Compare(sx, sy);
                        break;
                }
            }
            if (OrderOfSort == SortOrder.Descending)
                result = (-result);

            return result;
        }

        public int SortColumn
        {
            set
            {
                if (ColumnIndex == value)
                {
                    OrderOfSort = (OrderOfSort == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending);
                }
                ColumnIndex = value;
                try
                {
                    mySortTypeCode = Type.GetTypeCode(Type.GetType((myDataGridView.Columns[ColumnIndex]).Tag.ToString()));
                }
                catch
                {
                    mySortTypeCode = TypeCode.String;
                }
            }
            get { return ColumnIndex; }
        }

        public SortOrder Order
        {
            set { OrderOfSort = value; }
            get { return OrderOfSort; }
        }
    } //end class DataGridViewCustomSorter
} //end class MyDataGridHelper

這里有一些解決方案“ 使用SortCompare事件進行 自定義排序 ”和“ 使用IComparer接口進行自定義排序 ”:

http://msdn.microsoft.com/en-us/library/ms171608.aspx

您可以創建2個隱藏列。 將文本部分分配給第一個隱藏列,將數字部分分配給第二個隱藏列。 現在按這些隱藏列排序(第一列的alpha排序和第二列的數字排序)。

通過這種方式,您可以保留原始列以進行顯示,並使用2個隱藏列進行排序。

您可以將排序邏輯移動到數據庫查詢中,並讓它返回具有正確排序順序的其他列。

然后(沿着@True C Sharp的回答)你可以有一個包含這個值的隱藏列,並按此而不是顯示列進行排序。

這假定用於確定排序順序的邏輯可以在SQL中執行。 如果用於確定排序順序的算法很復雜,則這可能不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM