在DataGridView中显示合计,并且合计始终在最后一行

时间:2022-09-16 14:48:07

DataGridView提供数据的显示和排序功能,但没有合计的功能,本人曾想过通过绑定DataView,然后直接给DataView增加一个,合计是可以显示出来,但通过列标题排序就很难控制了,绑定的做法很麻烦,因为很多动作不受控。绑定不行,只能自己创建DataGridView的列和行了,自己控制排序等。

为DataGridView增加列和行:

/// <summary>
        /// 根据DataTable创建DataGridView。
        /// </summary>
        /// <param name="table"></param>
        private void BuidGrid(DataTable table)
        {
            for (int i = 0; i < table.Columns.Count; i++)
            {
                DataColumn dcol = table.Columns[i];
                DataGridViewColumn column = new DataGridViewColumn(new DataGridViewTextBoxCell());
                dtgCount.Columns.Add(column);
                column.SortMode = DataGridViewColumnSortMode.Automatic;
                column.HeaderText = dcol.ColumnName;
                column.Name = dcol.ColumnName;
                if (i == 0)
                {
                    column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
                }
                else
                {
                    column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                    if (i == table.Columns.Count - 1)
                        column.DefaultCellStyle.BackColor = Color.Yellow;
                }
            }
            foreach (DataRow row in table.Rows)
            {
                int index = dtgCount.Rows.Add();
                DataGridViewRow vRow = dtgCount.Rows[index];
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    vRow.Cells[i].Value = row[i];
                }
            }
            //增加多一个合计的行
            int countIndex = dtgCount.Rows.Add();
            DataGridViewRow countRow = dtgCount.Rows[countIndex];
            countRow.Cells[0].Value = "合计";
            for (int i = 1; i < table.Columns.Count; i++)
            {
                countRow.Cells[i].Value = table.Compute("Sum([" + table.Columns[i].ColumnName + "])", "");
                countRow.DefaultCellStyle.BackColor = Color.Yellow;
            }
        }

    这样合计行就在最下面了,现在要解决的是排序的问题了,在上面的数据中,除了第一列,其他列为Int32类型,合计行好像是字符串类型,没有深入研究原因。

 

        private void dtgCount_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
        {
            if (e.Column.Index == 0)
            {
                if (dtgCount.Rows[e.RowIndex1].Cells[0].Value.ToString() == "合计")
                {
                    if (e.Column.HeaderCell.SortGlyphDirection == SortOrder.Ascending)
                        e.SortResult = 1;
                    else
                        e.SortResult = -1;
                }
                else if (dtgCount.Rows[e.RowIndex2].Cells[0].Value.ToString() == "合计")
                {
                    if (e.Column.HeaderCell.SortGlyphDirection == SortOrder.Ascending)
                        e.SortResult = -1;
                    else
                        e.SortResult = 1;
                }
                else
                    e.SortResult = System.String.Compare(e.CellValue1.ToString(), e.CellValue2.ToString());

            }
            else
            {
                if (dtgCount.Rows[e.RowIndex1].Cells[0].Value.ToString() == "合计")
                {
                    if (e.Column.HeaderCell.SortGlyphDirection == SortOrder.Ascending)
                        e.SortResult = 1;
                    else
                        e.SortResult = -1;
                }
                else if (dtgCount.Rows[e.RowIndex2].Cells[0].Value.ToString() == "合计")
                {
                    if (e.Column.HeaderCell.SortGlyphDirection == SortOrder.Ascending)
                        e.SortResult = -1;
                    else
                        e.SortResult = 1;
                }
                else
                {
                    string strc1 = e.CellValue1.ToString();
                    string strc2 = e.CellValue2.ToString();
                    int c1 = string.IsNullOrEmpty(strc1) ? 0 : Convert.ToInt32(strc1);
                    int c2 = string.IsNullOrEmpty(strc2) ? 0 : Convert.ToInt32(strc2);
                    int result = c1 - c2;
                    e.SortResult = result > 0 ? 1 : (result < 0 ? -1 : 0);
                }
            }
            e.Handled = true;
        }

 

  排序的算法测试了很长时间,原因是不很清楚系统的快速排序算法,原以为合计行在最后,所以只对e.RowIndex2作判断,结果总是出问题,系统自动退出,可能排序使用的是异步线程吧,在系统里捕捉不到异常的,后来对e.RowIndex1和e.RowIndex2分别作判断,并根据SortOrder来确定返回的值,问题解决。在比较中可能有些操作效率不高,使用者可根据需要修改。

      如果想封装为通过的控制,可以重写DataSource属性,通过反射来生成行和列;重写OnSortCompare方法等,由于使用不多,所以本人只使用上面的方法,代码量也不多,比较灵活。