【问题标题】:Can't sort C# DataGridView column as integers无法将 C# DataGridView 列排序为整数
【发布时间】:2019-07-10 19:55:40
【问题描述】:

我的 Windows 窗体应用程序中有一个DataGridView gridFilas,它有两列,第二列总是包含可以转换为整数的字符串。当我单击对其进行排序时,它被排序为字符串,结果如下:

1, 11, 2, 22

但我需要将其排序为整数,例如:

1, 2, 11, 22

我已经尝试了this question 的所有答案,但没有一个起作用,顺便说一句,接受的答案,它不起作用,因为SortCompare 事件没有被触发,因为this

所以到目前为止我尝试的是添加一个ColumnHeaderMouseClick 并使用以下命令对其进行排序:

private void gridFilas_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{

    // this for loop has been added in a vain hope of converting all elements to integer to see if it works...
    for (int i = 0; i < gridFilas.Rows.Count; i++)
    {
        string v = gridFilas.Rows[i].Cells[1].Value.ToString();
        gridFilas.Rows[i].Cells[1].Value = Convert.ToInt32(v);
    }

    if (queuesSortedAscending)
    {
        gridFilas.Sort(gridFilas.Columns["Tamanho_Fila"], System.ComponentModel.ListSortDirection.Descending);
    }
    else
    {
        gridFilas.Sort(gridFilas.Columns["Tamanho_Fila"], System.ComponentModel.ListSortDirection.Ascending);
    }
    queuesSortedAscending = !queuesSortedAscending;

}

在创建时设置数据源(Form 的构造函数):

dsComponentes = new DataSet();
// ... more code 
gridFilas.DataSource = dsComponentes.Tables["Queue"];

每当我向 DataSource 添加新行时,我都会确保它被解析为 int:

DataRow qlinha = dsComponentes.Tables["Queue"].NewRow();
qlinha["Nome_Fila"] = process;
qlinha["Tamanho_Fila"] = Int32.Parse(status);
dsComponentes.Tables["Queue"].Rows.Add(qlinha);

我也尝试过事先更改列的数据类型:

dsComponentes.Tables["Queue"].Columns["Tamanho_Fila"].DataType = typeof(int);

所以,我不知道还能做什么,我只需要将它作为整数而不是字符串来排序。欢迎任何解决方案。

【问题讨论】:

  • the second column always contains strings that can be converted to integers DGV 列是类型化的 - 使用整数列使用自然排序的自定义排序器。关于这两个主题的大量文档和帖子

标签: c# windows-forms-designer


【解决方案1】:

您永远不会显示您在哪里创建要绑定到的 DataTable (dsComponentes.Tables["Queue"]),但是当您添加该列时,您应该能够表明它是一个 int

var dataTable = new DataTable();
dataTable.Columns.Add("ColumnName", typeof(int));

这将导致绑定的DataGridView 将该列排序为整数。

如果您使用设计器创建您的DataSet,那么在列集合编辑器中似乎也有一个DataType。您可以在该列上将类型设置为System.Int32,它将按照您的预期进行排序。

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
   static class Program
   {
      /// <summary>
      /// The main entry point for the application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);

         var frm = new Form()
         {
            Text = "Data Grid View Form",
            Name = "DataGridViewForm",
            Size = new System.Drawing.Size(400, 400)
         };
         var dataGridView1 = new DataGridView();

         var dataTable = new DataTable();
         dataGridView1.DataSource = dataTable;
         dataGridView1.Dock = DockStyle.Fill;

         dataTable.Columns.Add("Id", typeof(int));
         dataTable.Columns.Add("IdAsString", typeof(string));
         var r1 = dataTable.NewRow();
         r1["Id"] = 1;
         r1["IdAsString"] = "1";
         dataTable.Rows.Add(r1);

         var r2 = dataTable.NewRow();
         r2["Id"] = 11;
         r2["IdAsString"] = "11";
         dataTable.Rows.Add(r2);

         var r3 = dataTable.NewRow();
         r3["Id"] = 2;
         r3["IdAsString"] = "2";
         dataTable.Rows.Add(r3);

         var r4 = dataTable.NewRow();
         r4["Id"] = 22;
         r4["IdAsString"] = "22";
         dataTable.Rows.Add(r4);

         frm.Controls.Add(dataGridView1);

         Application.Run(frm);
      }
   }
}

【讨论】:

    【解决方案2】:

    最简单的方法是使用 nuget 包:Equin ApplicationFramework BindingListView

    它与标准的 .net BindingList 非常相似,只是它包含排序函数。

    • 将 BindingListView nuget 导入您的项目中
    • 使用 Visual Studio 设计器创建表单
    • 使用工具箱将 BindingSource 添加到表单中
    • 转到此 BindingSource 的属性,选择 DataSource,添加项目数据源,选择 Object 并添加要在 DataGridView 中显示的项目类
    • 现在使用工具箱添加您的 DataGridView
    • 在 DataGridView 的属性中选择 BindingSource 作为数据源。

    现在您的类的所有公共属性都将显示为 DataGridView 中的列。相应地编辑列:删除您不会使用的列。

    在我的示例中,我将对 Person 序列进行排序:

    class Person
    {
        public int Id {get; set;}
        public string Name {get; set;}
        public DateTime BirthDate {get; set;}
    }
    

    转到您的 Form1 课程。我们将从 nuget 包中添加一个 BindingListView 作为成员。 在构造函数中,我们将其分配给分配给 DataGridView 的 bindingsource。

    class Form
    {
        // the BindingListView from the nuget package:
        private readonly BindingListView<Person> sortableBindingListView;
    
        // constructor
        public Form1()
        {
            InitializeComponent();
    
            // make sure there is a Components Container, that will dispose
            // the components upon disposal of the form
            if (this.components == null)
            {
                this.components = new System.ComponentModel.Container();
            }
    
            // construct the sortable BindingListView for Persons:
            this.sortableBindingListView = new BindingListView<Person>(this.components);
    
            // create some Persons:
            var persons = new Person[]
            {
                new Person{Id = 1, Name = "F", BirthDate = new DateTime(2000, 1, 1)},
                new Person{Id = 2, Name = "A", BirthDate = new DateTime(1998, 4, 7)},
                new Person{Id = 3, Name = "C", BirthDate = new DateTime(2011, 3, 8)},
                new Person{Id = 4, Name = "Z", BirthDate = new DateTime(1997, 2, 3)},
                new Person{Id = 5, Name = "K", BirthDate = new DateTime(2003, 9, 5)},
            };
    
            // Assign the DataSources:
            this.sortableBindingListView.DataSource = persons;
            this.dataGridView1.DataSource = this.sortableBindingListView;
        }
    }
    

    这足以让您的排序工作。你不必添加任何额外的东西。单击列后,该列将被过滤。

    一些有趣的功能:

    private Person SelectedPerson
    {
        get {return ((ObjectView<Person>)this.SortableBindingSource.Current)?.Object; }
    }
    
    private void DisplayPersons (IEnumerable<Person> personsToDisplay)
    {
        this.SortableBindingSource.DataSource = personsToDisplay.ToList();
        this.SortableBindingSource.Refresh(); // this will update the DataGridView
    }
    
    private IEnumerable<Person> DisplayedPersons
    {
        get {return this.SortableBindingSource; }
        // BindingListview<T> implements IEnumerable<T>
    }
    

    这就是全部。您无需创建特殊功能即可对鼠标单击进行排序。排序将自动完成,包括决定排序顺序并显示正确的排序字形。

    如果您想以编程方式排序:

    // sort columnPropertyA in descending order:
    this.SortableBindingSource.Sort(this.columnPropertyA.ListsortDirection.Descending);
    

    BindingListView 的一大优点是过滤选项:

    // show only items where Name not null:
    this.SortableBindingSource.ApplyFilter(person => person.Name != null);
    
    // remove the filter:
    this.SortableBindingSource.RemoveFilter();
    

    我不确定在应用或删除过滤器后是否需要 Refresh()。

    【讨论】:

      猜你喜欢
      • 2017-07-22
      • 2010-09-13
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-28
      相关资源
      最近更新 更多