DataGridView增加汇总行

.net DataGridView不支持汇总行,使用起来多有不便,本想重写此控件,以前做Web项目时曾用Javascript写过与WinForm中的DataGridView类似的控件,但分析微软的代码后感觉重写非常的烦,所以采用改造原控件的方式,重写OnLayout函数,当布局完毕,通过反射修改网络区的大小,在底部留出汇总条的位置,将汇总条嵌在其中,这样网格内容与汇总条内容不会相互影响,同时在涉及布局和滚动的事件中对汇总行的位置尺寸重新计算,以保证与网格与汇总条对齐。

汇总行使用Panel包含的ListView来显示汇总行内容,考虑列冻结的情况,leftPanel用来显示冻结内容rightPanel显示可滚动内容,汇总行在网络主体添加列时生成相应的对,默认无汇总动作,对汇总行列的 SumMode 设置相应的值可启用汇总、计数、平均值等动作(程序需补充),代码如下,希望对需要的人有所帮助

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

namespace Nauja.GridFooter
{
    public partial class DataGridViewEx : DataGridView
    {
        private DataGridFooter _Footer = new DataGridFooter();

        public DataGridFooter Footer
        {
            get { return _Footer; }
            set { _Footer = value; }
        }
        public bool FooterVisible
        {
            get { return _Footer.Visible; }
            set { _Footer.Visible = value; }
        }
       

        public DataGridViewEx()
        {
            this.Controls.Add(this._Footer);
           
            this.Scroll += new ScrollEventHandler(DataGridViewEx_Scroll);
            this.ColumnWidthChanged += new DataGridViewColumnEventHandler(DataGridViewEx_ColumnWidthChanged);
            this.CellBeginEdit += new DataGridViewCellCancelEventHandler(DataGridViewEx_CellBeginEdit);
            this.CellEndEdit += new DataGridViewCellEventHandler(DataGridViewEx_CellEndEdit);
            this.ColumnAdded+=new DataGridViewColumnEventHandler(DataGridViewEx_ColumnAdded);
            this.RowHeadersWidthChanged += new EventHandler(DataGridViewEx_RowHeadersWidthChanged);
            this.SizeChanged += new EventHandler(DataGridViewEx_SizeChanged);
        }

        void DataGridViewEx_SizeChanged(object sender, EventArgs e)
        {
            RefreshFooter();
        }

        void DataGridViewEx_RowHeadersWidthChanged(object sender, EventArgs e)
        {
            _Footer.RowHeaderWidth = this.RowHeadersWidth;
            RefreshFooter();
        }

        void DataGridViewEx_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
        {
            _Footer.Columns.Add(new DataGridFooterColumn(DataGridFooterSumMode.None));

            RefreshFooter();
        }

 


        private object cellTempValue=0;

        void DataGridViewEx_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            cellTempValue = this[e.ColumnIndex, e.RowIndex].Value;
        }

        void DataGridViewEx_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (this[e.ColumnIndex,e.RowIndex].Value != cellTempValue)
            {
                if (_Footer.Columns[e.ColumnIndex].SumMode == DataGridFooterSumMode.Sum)
                {
                    decimal v=0, t=0;
                    try
                    {
                        t = ("" + cellTempValue == "" ? (decimal)0 : decimal.Parse("" + cellTempValue));
                        v = ("" + this[e.ColumnIndex, e.RowIndex].Value == "" ? (decimal)0 : decimal.Parse("" + this[e.ColumnIndex, e.RowIndex].Value));
                    }
                    catch (FormatException)
                    {
                        this[e.ColumnIndex, e.RowIndex].Value = "";
                        v = 0;
                    }
                    _Footer.Columns[e.ColumnIndex].Value = (decimal)_Footer.Columns[e.ColumnIndex].Value - t + v;
                }
                cellTempValue = 0;
            }
        }

        void DataGridViewEx_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            _Footer.Columns[e.Column.Index].Width = e.Column.Width;
            RefreshFooter();
        }
        private int BorderWidth
        {
            get { return 1; }
        }
        private void RefreshFooter()
        {
            Rectangle rect = new Rectangle();
            if (HorizontalScrollBar.Visible)
            {
                rect.X = BorderWidth;
                rect.Y = this.Height - _Footer.Height - HorizontalScrollBar.Height - BorderWidth;
                rect.Width = this.Width - BorderWidth * 2;
                rect.Height = _Footer.Height;
                _Footer.LayoutControl(rect);
            }
            else
            {
                rect.X = BorderWidth;
                rect.Y = this.Height - _Footer.Height - BorderWidth;
                rect.Width = this.Width - BorderWidth * 2;
                rect.Height = _Footer.Height;
                _Footer.LayoutControl(rect);
            }
            _Footer.Refresh();
        }


        void DataGridViewEx_Scroll(object sender, ScrollEventArgs e)
        {
            _Footer.ScrollWithParent(this.HorizontalScrollBar.Value);
        }

        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);

            Type t = this.GetType();
            FieldInfo tLayout = t.BaseType.GetField("layout", BindingFlags.NonPublic | BindingFlags.Instance);
            if (tLayout == null)
                return;

            Object layout = tLayout.GetValue(this);
           
            if (layout == null)
                return;
           
            FieldInfo tDataClient = layout.GetType().GetField("Data");
            Rectangle dataClient = (Rectangle)tDataClient.GetValue(layout);
            if(this.ColumnHeadersHeight+(this.HorizontalScrollBar.Visible?this.HorizontalScrollBar.Height:0)+dataClient.Height>this.Height-this.HorizontalScrollBar.Height){
                dataClient = new Rectangle(dataClient.X, dataClient.Y, dataClient.Width, dataClient.Height - this.HorizontalScrollBar.Height);
                tDataClient.SetValue(layout, dataClient);
                RefreshFooter();
            }
        }
    }

    public class DataGridFooter:Panel
    {
        private ImageList _ImgList = new ImageList();
        private Panel _LeftPanel=new Panel();
        private Panel _RightPanel=new Panel();
        internal ListView _LeftView=new ListView();
        internal ListView _RightView = new ListView();
        private int _Frozen = 0;
        private DataGridViewEx _DataGridViewEx = null;

        public DataGridFooterColumnCollection Columns =null;
           

        public DataGridViewEx DGViewEx
        {
            get { return _DataGridViewEx; }
            set { _DataGridViewEx = value; }
        }

        public string RowHeaderText
        {
            get { return this._LeftView.Items[0].SubItems[0].Text; }
            set
            {
                this._LeftView.Items[0].SubItems[0].Text = value;
                this._RightView.Items[0].SubItems[0].Text = value;
            }
        }
        public int RowHeaderWidth
        {
            get { return this._LeftView.Columns[0].Width; }
            set
            {
                this._LeftView.Columns[0].Width = value;
                this._RightView.Columns[0].Width = value;
            }
        }


        public DataGridFooter(){
            this._ImgList.ImageSize = new Size(1, 18);
            this.Columns = new DataGridFooterColumnCollection(this);

            this.BorderStyle = BorderStyle.None;
            this._LeftPanel.BorderStyle = BorderStyle.None;
            this._RightPanel.BorderStyle = BorderStyle.None;
            this._LeftView.BorderStyle = BorderStyle.None;
            this._RightView.BorderStyle = BorderStyle.None;

            this.SuspendLayout();

            this.Height = 18;
            //
            //_LeftPanel
            //
            this._LeftPanel.Margin = new Padding(0);
            this._LeftPanel.Height = 18;

            //
            //_RightPanel
            //
            this._RightPanel.Margin = new Padding(0);
            this._RightPanel.Height = 18;

            //
            //_LeftView
            //
            this._LeftView.Margin = new Padding(0);
            this._LeftView.Height = 18;
            this._LeftView.Columns.Add("");
            this._LeftView.Items.Add("合计");

            this._LeftView.AutoArrange = false;
            this._LeftView.BackColor = System.Drawing.SystemColors.ActiveCaptionText;

            this._LeftView.BackgroundImage = global::GridFoot.Properties.Resources.bg;
            this._LeftView.BackgroundImageTiled = true;
            this._LeftView.BorderStyle = System.Windows.Forms.BorderStyle.None;

            this._LeftView.GridLines = true;
            this._LeftView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
           
            this._LeftView.LabelWrap = false;
            this._LeftView.Name = "leftView";
            this._LeftView.Scrollable = false;
            this._LeftView.ShowGroups = false;
            this._LeftView.SmallImageList = this._ImgList;
            this._LeftView.UseCompatibleStateImageBehavior = false;
            this._LeftView.View = System.Windows.Forms.View.Details;

            //
            //_RightView
            //
            this._RightView.Margin = new Padding(0);
            this._RightView.Height = 18;
            this._RightView.Columns.Add("");
            this._RightView.Items.Add("合计");
            this._RightView.AutoArrange = false;
            this._RightView.BackColor = System.Drawing.SystemColors.ActiveCaptionText;
            this._RightView.BackgroundImage = global::GridFoot.Properties.Resources.bg;
            this._RightView.BackgroundImageTiled = true;
            this._RightView.BorderStyle = System.Windows.Forms.BorderStyle.None;

            this._RightView.GridLines = true;
            this._RightView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;

            this._RightView.LabelWrap = false;
            this._RightView.Name = "rightView";
            this._RightView.Scrollable = false;
            this._RightView.ShowGroups = false;
            this._RightView.SmallImageList = this._ImgList;
            this._RightView.UseCompatibleStateImageBehavior = false;
            this._RightView.View = System.Windows.Forms.View.Details;
     

            this._LeftPanel.Controls.Add(this._LeftView);
            this._RightPanel.Controls.Add(this._RightView);

            this.Controls.Add(_LeftPanel);
            this.Controls.Add(_RightPanel);

            this.ResumeLayout(false);
            this.ParentChanged += new EventHandler(DataGridFooter_ParentChanged);
        }

        void DataGridFooter_ParentChanged(object sender, EventArgs e)
        {
            if (this.Parent != null && !(this.Parent is DataGridViewEx))
                throw new Exception("不能将DataGridView添加到非DataGridViewEx控件之中");
            _DataGridViewEx = (DataGridViewEx)this.Parent;
        }

        internal void ScrollWithParent(int scrollValue)
        {
            int leftw = _DataGridViewEx.RowHeadersVisible ? _DataGridViewEx.RowHeadersWidth : 0;
            if (_Frozen > 0)
            {
                for (int i = 0; i < _Frozen; i++)
                    leftw += _DataGridViewEx.Columns[i].Width;
            }
            _RightView.Left = -leftw-scrollValue+1;
        }

        public void LayoutControl(Rectangle rect)
        {
            //冻结列
            _Frozen = 0;
            this.RowHeaderWidth = this._DataGridViewEx.RowHeadersWidth-3;
            int sumw = 0;
            for(int i=0;i<this.Columns.Count&&i<this._DataGridViewEx.Columns.Count;i++)
            {
                this.Columns[i].Width=this._DataGridViewEx.Columns[i].Width;
                sumw += this.Columns[i].Width;
            }
            sumw += RowHeaderWidth;

            this._LeftView.Width = this._RightView.Width = sumw;
           
            for (int i = _DataGridViewEx.Columns.Count - 1; i >= 0; i--)
            {
                if (_DataGridViewEx.Columns[i].Frozen)
                {
                    _Frozen = ++i;
                    break;
                }
            }

            int leftw = _DataGridViewEx.RowHeadersVisible ? _DataGridViewEx.RowHeadersWidth : 0;
            if (_Frozen > 0)
            {
                for (int i = 0; i < _Frozen; i++)
                    leftw += _DataGridViewEx.Columns[i].Width;
            }
            _LeftPanel.Width = leftw;
            _LeftPanel.Left =_LeftView.Left = rect.Left;

            _RightPanel.Left = leftw + rect.Left;
            _RightPanel.Width = sumw;// rect.Width - leftw;

            _RightView.Left = -(_DataGridViewEx.RowHeadersVisible ? _DataGridViewEx.RowHeadersWidth : 0)+1;

            this.Width = rect.Width;
            this.Top = rect.Top;
            this.Left = rect.Left;

        }
    }
    public enum DataGridFooterSumMode{Sum,Average,Count,None}

    public class DataGridFooterColumn
    {
        private int _Width = 20;
        private object _Value;
        private DataGridFooterSumMode _SumMode = DataGridFooterSumMode.None;
        public string FormatStr;
        private DataGridFooter _DGFooter;
        internal int _ColumnIndex = -1;
        public string Text
        {
            get { return ""+_DGFooter._LeftView.Items[0].SubItems[_ColumnIndex].Text; }
            set {
                _DGFooter._LeftView.Items[0].SubItems[_ColumnIndex].Text = value;
                _DGFooter._RightView.Items[0].SubItems[_ColumnIndex].Text = value;
            }
        }

        public object Value
        {
            get { return _Value; }
            set
            {
                _Value = value;
                Text = "" + value;
            }
        }

        public DataGridFooterSumMode SumMode
        {
            get { return _SumMode; }
            set {
                _SumMode = value;
                if (_SumMode == DataGridFooterSumMode.Sum||_SumMode==DataGridFooterSumMode.Count||_SumMode==DataGridFooterSumMode.Average)
                    _Value = (decimal)0;
            }
        }

        public DataGridFooter DGFooter
        {
            get { return _DGFooter; }
            set { _DGFooter = value; }
        }

        public int Width
        {
            get { return _Width; }
            set
            {
                _Width = value;
                if (_ColumnIndex >= 0)
                {
                    this._DGFooter._LeftView.Columns[_ColumnIndex].Width = value;
                    this._DGFooter._RightView.Columns[_ColumnIndex].Width = value;
                }
            }
        }

        public DataGridFooterColumn()
        {
       
        }

        public DataGridFooterColumn(DataGridFooterSumMode summode)
        {
            this.SumMode = summode;
        }

    }

    public class DataGridFooterColumnCollection:CollectionBase
    {
        private DataGridFooter _DGFooter = null;
        public DataGridFooter DGFooter
        {
            get { return _DGFooter; }
            set { _DGFooter = value;
            for (int i = this.Count - 1; i >= 0; i--)
                this[i].DGFooter = value;
            }
        }
        public DataGridFooterColumn this[int index]{
            get
            {
                if (index >= 0 && index < List.Count)
                    return (DataGridFooterColumn)List[index];
                else
                    return null;
            }
        }
       
        public DataGridFooterColumnCollection()
        {

        }

        public DataGridFooterColumnCollection(DataGridFooter footer)
        {
            _DGFooter = footer;
        }
        internal void Add(DataGridFooterColumn column)
        {
            column.DGFooter = this.DGFooter;
           

            List.Add(column);
            column._ColumnIndex = List.Count;
            _DGFooter._LeftView.Columns.Add("", column.Width);
            _DGFooter._LeftView.Items[0].SubItems.Add("");
            _DGFooter._RightView.Columns.Add("", column.Width);
            _DGFooter._RightView.Items[0].SubItems.Add("");
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值