一. 合计行不参与排序
datagridview是采用datatable绑定datasource的情况下,最后一行是合计行,最后一行不参与排序而一直在最下面一行。主要是要实现CellMouseClick和Sorted方法,点击了Header后先保存最后一行合计行的内容,并Remove该行,然后按照系默认的方式排序,Sorted方法在排序后执行,把最后一行再添加到datagridview的末尾。

对于另外一种非绑定datatable的,而手动print出来的datagridview,可以采用重写Sort_compare方法,使得最后一行不参与排序,具体可以参看这里,注:此种方式发现的问题有两个。1.如果表格内容较多,一行行的将数据打印出来会使得列表刷新反应较慢。2.比较列的元素需要实现IComparable,特别是如果该列中有空或者NULL的时候,系统可能会不知道如何NULL与其他元素比较大小,会报错。

        private List<object[]> lastRow = new List<object[]>();
        private int colindex = 0;
        private string lastSortColName = null;
        private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.RowIndex >= 0 || this.dataGridView1.Rows.Count == 0)
                return;

            if (lastRow.Count == 0)
            {
                colindex = e.ColumnIndex;
                int index = this.dataGridView1.Rows.Count - 1;
                lastRow.Add(((DataTable)this.dataGridView1.DataSource).Rows[index].ItemArray);

                this.dataGridView1.Rows.Remove(this.dataGridView1.Rows[this.dataGridView1.Rows.Count - 1]);
            }
        }

        private void dataGridView1_Sorted(object sender, EventArgs e)
        {
            if (lastRow.Count == 0)
                return;

            DataTable dt = ((DataTable)this.dataGridView1.DataSource);
            DataView dv = dt.DefaultView;
            dv.Sort = dt.Columns[colindex].ColumnName;
            if(this.lastSortColName == null || this.lastSortColName != dv.Sort)
            {
                lastSortColName = dv.Sort;
                dv.Sort = dv.Sort + " ASC";
            }
            else
            {
                dv.Sort = dv.Sort + " DESC";
                lastSortColName = null;
            }
            dt = dv.ToTable();
            dt.Rows.Add(lastRow[0]);
            lastRow.Clear();
            this.dataGridView1.DataSource = dt;

        }

注: datatable的DefaultView中Sort的 columnName + “ASC/DESC”的排序依据和执行sql中构建order by的结果不一致(我的是mysql utf-8),就是说datagridview采用的默认元素比较策略和sql的不一致,尤其是你自己实现了Sort_Compare的情况下(指定datasource模式该事件不会触发)。因此在刷新datagridview数据的时候如果要保持之前的排序规则,不用利用sql的order,而设置结果的datatable的DefaultView的Sort,并table = toTable().

二. 表格最左侧添加行号

在每行左边的可点击区域添加行号,并在最后一行添加合计。

        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            try
            {
                SolidBrush v_SolidBrush = new SolidBrush(dataGridView1.RowHeadersDefaultCellStyle.ForeColor);
                int v_LineNo = 0;
                v_LineNo = e.RowIndex + 1;

                int x = 15;
                int y = 5;
                string v_Line = v_LineNo.ToString();
                if (e.RowIndex == this.dataGridView1.Rows.Count - 1)     //最后一行row
                {
                    v_Line = "合计";
                    x = 5;
                }
                e.Graphics.DrawString(v_Line, e.InheritedRowStyle.Font, v_SolidBrush, e.RowBounds.Location.X + x, e.RowBounds.Location.Y + y);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

三. 打印时候的问题

c#的打印实际上是自己把需要打印的数据利用事件,把内容画在一块画布上,每次打印一页都会调用打印文档PrintDocument象所绑定的PrintPage函数。很多C#的打印控件在设置完打印属性后会自动先生成打印预览,然后点击预览界面上的打印如果现打印结果和预览结果不一致,特别是有一堆随机大小的空白的话,需要确认所绑定的printPage函数没有使用什么全局的变或者至少每次调用的时候变量都被正确的初始化,因为打印预览是会调用绑定的printPage函数,然后点打印实际上还是会用,重绘一遍printDocument发送给打印机,而不是把预览的printPreviewDialog中的Document直接发送去打印,因此可能在生成打印预览和生成真正向打印机传递绘制的printDocument时某些变量,宽度之类的数据不一致而导致跟预览结果不一致相当郁闷,折腾了好几天。结果就是没有在绑定的PrintPage函数中每次先把纵坐标设置为最上面。

转载请注明来源:Leoncom-《C#的datagridview一些代码》
Trackback

no comment untill now

Add your comment now