簡體   English   中英

如何根據其列內容對DataGridView進行排序?

[英]How to sort a DataGridView based on its column content?

這里GrdView是一個DataGridView。 並且'obj.Code'是字母數字類型的(例如R12,BA3,BA21 ...)

private SortableBindingList<myClass> objList = new SortableBindingList<myClass>();

DataTable table = new DataTable();
table.Columns.Add("code", typeof(string));

foreach (var obj in objList)
{
    table.Rows.Add(obj.Code);
}

GrdView.DataSource = table;

通過單擊其列標題對DataGridView進行排序,但是排序為字母數字。 我只想按其數字內容(而不是前導字母)對DataGridView的列進行排序。

解決此問題的最簡單方法是添加僅包含數字的另一列。 您實際上無法根據單元格的子部分對數組進行排序。

排序將必須進行大量比較(至少n * ln(n)),因此,對於每次訪問都轉換字符串不是一個好習慣。

您應該做的只是將列轉換為等效的數字形式,然后按該列排序。

排序之后,您可以刪除該列,然后將其全部傳遞以HTML形式呈現。

兩種選擇-

  1. 您可以捕獲SortCompare事件並修改其行為以適合您的需求。 在這里看看第二個示例-http: //msdn.microsoft.com/zh-cn/library/ms171608(v=vs.90).aspx

  2. 您可以捕獲ColumnHeaderMouseClick事件 ,然后使用適合您需求的IComparer手動運行Sort

就像pid在他的回答中說的那樣,考慮到大量元素,在實現比較邏輯時要考慮性能。 但是,在實施復雜的解決方案之前,我將首先對大量數據進行測試,以確保存在問題。

您需要創建另一列進行排序(可以將其設為Visible屬性= false)。 將所有這些代碼粘貼到新的Windows窗體中,它將完全按照您所描述的那樣工作(刪除FormX.designer.cs文件)。 SortableCode列使用正則表達式刪除前導字母字符。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace StackOverflowQuestion21361045
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public class myClass
        {
            public string Code { get; set; }

            public string SortableCode
            {
                get
                {
                    return Regex.Replace(Code, @"^[^\d]+", string.Empty);
                }
            }
        }

        private readonly SortableBindingList<myClass> objList = new SortableBindingList<myClass>();

        private void Form1_Load(object sender, EventArgs e)
        {
            objList.Add(new myClass {Code = "A23"});
            objList.Add(new myClass {Code = "B12"});
            objList.Add(new myClass {Code = "C04" });
            dataGridView1.DataSource = objList;
            dataGridView1.Sort(dataGridView1.Columns[1], ListSortDirection.Ascending);
        }

        private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            DataGridViewColumn newColumn = dataGridView1.Columns[e.ColumnIndex];
            DataGridViewColumn previouslySortedColumn = dataGridView1.SortedColumn;
            ListSortDirection direction;

            if (newColumn == dataGridView1.Columns[0])
                newColumn = dataGridView1.Columns[1]; //if the user sorts by code, change the column so as to sort by SortableCode
            // If oldColumn is null, then the DataGridView is not sorted. 
            if (previouslySortedColumn != null)
            {
                // Sort the same column again, reversing the SortOrder. 
                if (previouslySortedColumn == newColumn &&
                    dataGridView1.SortOrder == SortOrder.Ascending)
                {
                    direction = ListSortDirection.Descending;
                }
                else
                {
                    // Sort a new column and remove the old SortGlyph.
                    direction = ListSortDirection.Ascending;
                    previouslySortedColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
                }
            }
            else
            {
                direction = ListSortDirection.Ascending;
            }

            // Sort the selected column.
            dataGridView1.Sort(newColumn, direction);
            newColumn.HeaderCell.SortGlyphDirection =
                direction == ListSortDirection.Ascending ?
                SortOrder.Ascending : SortOrder.Descending;
        }

        private void dataGridView1_DataBindingComplete(object sender,
            DataGridViewBindingCompleteEventArgs e)
        {
            // Put each of the columns into programmatic sort mode. 
            foreach (DataGridViewColumn column in dataGridView1.Columns)
            {
                column.SortMode = DataGridViewColumnSortMode.Programmatic;
            }
        }

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 0);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(284, 261);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dataGridView1_ColumnHeaderMouseClick);
            this.dataGridView1.DataBindingComplete += new System.Windows.Forms.DataGridViewBindingCompleteEventHandler(this.dataGridView1_DataBindingComplete);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 261);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.DataGridView dataGridView1;

        public class SortableBindingList<T> : BindingList<T>
        {
            private ArrayList sortedList;
            private ArrayList unsortedItems;
            private bool isSortedValue;

            public SortableBindingList()
            {
            }

            public SortableBindingList(IList<T> list)
            {
                foreach (object o in list)
                {
                    this.Add((T)o);
                }
            }

            protected override bool SupportsSearchingCore
            {
                get
                {
                    return true;
                }
            }

            protected override int FindCore(PropertyDescriptor prop, object key)
            {
                PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
                T item;

                if (key != null)
                {
                    for (int i = 0; i < Count; ++i)
                    {
                        item = (T)Items[i];
                        if (propInfo.GetValue(item, null).Equals(key))
                            return i;
                    }
                }
                return -1;
            }

            public int Find(string property, object key)
            {
                PropertyDescriptorCollection properties =
                    TypeDescriptor.GetProperties(typeof(T));
                PropertyDescriptor prop = properties.Find(property, true);

                if (prop == null)
                    return -1;
                else
                    return FindCore(prop, key);
            }

            protected override bool SupportsSortingCore
            {
                get { return true; }
            }


            protected override bool IsSortedCore
            {
                get { return isSortedValue; }
            }

            ListSortDirection sortDirectionValue;
            PropertyDescriptor sortPropertyValue;

            protected override void ApplySortCore(PropertyDescriptor prop,
                ListSortDirection direction)
            {
                sortedList = new ArrayList();

                Type interfaceType = prop.PropertyType.GetInterface("IComparable");

                if (interfaceType == null && prop.PropertyType.IsValueType)
                {
                    Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);

                    if (underlyingType != null)
                    {
                        interfaceType = underlyingType.GetInterface("IComparable");
                    }
                }

                if (interfaceType != null)
                {
                    sortPropertyValue = prop;
                    sortDirectionValue = direction;

                    IEnumerable<T> query = base.Items;
                    if (direction == ListSortDirection.Ascending)
                    {
                        query = query.OrderBy(i => prop.GetValue(i));
                    }
                    else
                    {
                        query = query.OrderByDescending(i => prop.GetValue(i));
                    }
                    int newIndex = 0;
                    foreach (object item in query)
                    {
                        this.Items[newIndex] = (T)item;
                        newIndex++;
                    }
                    isSortedValue = true;
                    this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

                }
                else
                {
                    throw new NotSupportedException("Cannot sort by " + prop.Name +
                        ". This" + prop.PropertyType.ToString() +
                        " does not implement IComparable");
                }
            }

            protected override void RemoveSortCore()
            {
                int position;
                object temp;

                if (unsortedItems != null)
                {
                    for (int i = 0; i < unsortedItems.Count; )
                    {
                        position = this.Find("LastName",
                            unsortedItems[i].GetType().
                            GetProperty("LastName").GetValue(unsortedItems[i], null));
                        if (position > 0 && position != i)
                        {
                            temp = this[i];
                            this[i] = this[position];
                            this[position] = (T)temp;
                            i++;
                        }
                        else if (position == i)
                            i++;
                        else
                            unsortedItems.RemoveAt(i);
                    }
                    isSortedValue = false;
                    OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
                }
            }

            public void RemoveSort()
            {
                RemoveSortCore();
            }
            protected override PropertyDescriptor SortPropertyCore
            {
                get { return sortPropertyValue; }
            }

            protected override ListSortDirection SortDirectionCore
            {
                get { return sortDirectionValue; }
            }

        } 
    }
}

暫無
暫無

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

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