Winform DatagridView 数字列排序

问题描述 投票:0回答:7

我只使用一个简单的 DataGridView 来保存一堆数据(有趣的是)。

我在特定列中有小数。但是当按小数列排序时,它的排序是错误的。例如:

起始订单可能是:

  • 0.56
  • 3.45
  • 500.89
  • 20078.90
  • 1.56
  • 100.29
  • 2.39

结束顺序是:

  • 0.56
  • 100.29
  • 1.56
  • 20078.90
  • 2.39
  • 3.45
  • 500.89

如您所见,它从第一个数字开始排序。然后就这样下单了。

我想我可以将列设置为不同的“ColumnType”,这可能会自动完成。但没有“数字”或“小数”列类型。

我在 MSDN 上查找问题,我可以找到可以在 DataGridView 上使用的“排序”方法。但解释有点超出我的理解,并且示例没有使用数字,仅使用文本,因此我不知道应该如何进行切换。

任何帮助将不胜感激。

c# winforms datagridview
7个回答
9
投票

您可以通过使用以下代码在 DataGridView 上添加 SortCompare 事件的处理程序来解决此问题:

private void dataGridView1_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
    if (e.Column.Index == 0)
    {
        if (double.Parse(e.CellValue1.ToString()) > double.Parse(e.CellValue2.ToString()))
        {
            e.SortResult = 1;
        }
        else if (double.Parse(e.CellValue1.ToString()) < double.Parse(e.CellValue2.ToString()))
        {
            e.SortResult = -1;
        }             
        else
        {
            e.SortResult = 0;
        }
        e.Handled = true;
   }
}

MSDN 中有对 SortResult 值的描述:

如果第一个单元格将小于零 在第二个单元格之前排序;零 如果第一个单元格和第二个单元格有 等效值;大于零 是否对第二个单元格进行排序 在第一个单元之前。

请注意,在我的测试台中,唯一的数字列是第一个(索引为 0),因此这就是我检查列索引的原因。

此外,根据您的需求和数据,您可能需要优化我的代码 - 例如,如果由于某种原因您的列中有非数字数据,我的代码将引发异常。

您可能已经看过它,但是这里是有关自定义 DataGridView 排序的 MSDN 页面的链接。正如你所说,他们只处理文本。


6
投票

我也有同样的问题。我尝试使用 David Hall 提到的事件处理程序。我在定义 DataGridView 时使用了 ValueType 属性。现在它按双精度排序,无需自定义事件处理程序代码

dataGridView1.Columns[int index].ValueType = typeof(double);

您还可以使用

设置列格式
dataGridView2.Columns[int index].DefaultCellStyle.Format = string format;

1
投票

数字类型有一个内置的CompareTo函数,可以用作SortCompare事件的SortResult。

    private void dataGridView_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
    {
        if (e.Column.Index == 0)
        {
            e.SortResult = int.Parse(e.CellValue1.ToString()).CompareTo(int.Parse(e.CellValue2.ToString()));
            e.Handled = true;
        }
    }

这当然假设您知道首先放入 DataGridView 的类型。


1
投票

你的数据库列类型应该是 int 或 double 或 float,而不是 varchar 或其他...... 所以你必须改变数据库中的值类型...... 当您单击列标题时,您无需编写任何代码或直接排序的内容...


0
投票

它正在按字符排序。您需要使列类型浮点,以便它知道要应用什么比较运算符。

(也就是说,您需要使数据集中的列类型浮动,我相信这会起作用。)


0
投票

您的问题是

datagridview
按字符串排序。当您将该单元格复制到
string
时,尝试将
float
转换为
datagrid


0
投票

添加Datagridview列标题鼠标点击事件,代码如下:

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.RowIndex == -1 && e.ColumnIndex >= 0)
        {
            DataGridViewColumn clickedColumn = dataGridView1.Columns[e.ColumnIndex];

            // Check if the clicked column contains float values (adjust the check for your specific column)
            if (clickedColumn.Name == "colScore" || clickedColumn.Name == "colID")
            {
                // Sort using a custom comparer
                dataGridView1.Sort(new FloatColumnComparer(e.ColumnIndex));
            }
        }
    }

稍后我们需要添加自定义Comparer来进行排序。这里我们使用了 float 数据类型,这样我们就可以用它来对整数和浮点数进行排序。代码如下:

    private class FloatColumnComparer : IComparer
    {
        private readonly int columnIndex;
        private static bool Ascending = true;

        public FloatColumnComparer(int columnIndex)
        {
            this.columnIndex = columnIndex;
            Ascending ^= true;
        }

        public int Compare(object x, object y)
        {
            DataGridViewRow row1 = (DataGridViewRow)x;
            DataGridViewRow row2 = (DataGridViewRow)y;

            float value1, value2;

            if (float.TryParse(row1.Cells[columnIndex].Value.ToString(), out value1) &&
                float.TryParse(row2.Cells[columnIndex].Value.ToString(), out value2))
            {
                if (Ascending)
                    return value1.CompareTo(value2);
                else
                    return value2.CompareTo(value1);
            }

            return 0; // If parsing fails or values are not valid floats, consider them equal.
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.