现在的位置: 首页 > 综合 > 正文

ASPxGridViewHelper自定义多表头及合并单元格

2013年08月28日 ⁄ 综合 ⁄ 共 13892字 ⁄ 字号 评论关闭
using DevExpress.Web.ASPxGridView;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using System.Web.UI;
using System;
namespace Lcerp.Common
{
    public class ASPxGridViewHelper
    {
        #region 基本配置
        #region 多表头
        string header;
        bool isOpenMutiHeader = false;
        #endregion
        #region 合并单元格
        bool isOpenMergeCell = false;
        string fieldName;
        int[] notMergeNumbers = null;
        ASPxGridView grid;
        public ASPxGridView Grid { get { return grid; } }
        Dictionary<GridViewCommandColumn, TableCell> commandCells = new Dictionary<GridViewCommandColumn, TableCell>();
        Dictionary<GridViewDataColumn, TableCell> mergedCells = new Dictionary<GridViewDataColumn, TableCell>();
        Dictionary<TableCell, int> cellRowSpans = new Dictionary<TableCell, int>();
        #endregion
        #endregion
        #region 外部调用入口(初始化)
        public ASPxGridViewHelper(ASPxGridView grid)
        {
            this.grid = grid;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="grid">要操作的ASPxGridView</param>
        /// <param name="fieldName">根据哪个字段分组合并,例如单据编号</param>
        /// <param name="columnNumber">使后N列不进行合并,例如N=4,即后4列数据不参与合并</param>
        /// <param name="header">
        /// ASPxGridView多表头实现
        /// 表头格式定义方法:相邻父列#分隔 上下级空格分隔 相邻子级用逗号分隔
        /// </param>
        /// <param name="isOpenMutiHeader">是否启用多表头,默认关闭</param>
        /// <param name="isOpenMergeCell">是否启用合并单元格,默认关闭</param>
        public ASPxGridViewHelper(ASPxGridView grid, string fieldName, int[] notMergeNumbers, string header, bool isOpenMutiHeader, bool isOpenMergeCell)
        {
            this.grid = grid;
            this.fieldName = fieldName;
            this.header = header;
            this.isOpenMergeCell = isOpenMergeCell;
            this.isOpenMutiHeader = isOpenMutiHeader;
            this.notMergeNumbers = notMergeNumbers;
            Grid.HtmlRowCreated += new ASPxGridViewTableRowEventHandler(grid_HtmlRowCreated);
            Grid.HtmlDataCellPrepared += new ASPxGridViewTableDataCellEventHandler(grid_HtmlDataCellPrepared);
            Grid.HtmlCommandCellPrepared += new ASPxGridViewTableCommandCellEventHandler(grid_HtmlCommandCellPrepared);
        }
        #endregion
        #region 初始化准备
        void grid_HtmlDataCellPrepared(object sender, ASPxGridViewTableDataCellEventArgs e)
        {
            if (cellRowSpans.ContainsKey(e.Cell))
            {
                e.Cell.RowSpan = cellRowSpans[e.Cell];
            }
        }
        void grid_HtmlCommandCellPrepared(object sender, ASPxGridViewTableCommandCellEventArgs e)
        {
            if (cellRowSpans.ContainsKey(e.Cell))
            {
                e.Cell.RowSpan = cellRowSpans[e.Cell];
            }
        }
        void grid_HtmlRowCreated(object sender, ASPxGridViewTableRowEventArgs e)
        {
            #region 多表头
            if (isOpenMutiHeader)
            {
                ASPxGridView gv = sender as ASPxGridView;
                if (e.RowType == DevExpress.Web.ASPxGridView.GridViewRowType.Data && e.VisibleIndex == gv.PageIndex * gv.SettingsPager.PageSize)
                {
                    SplitTableHeader(e.Row, header);
                }
            }
            #endregion
            #region 合并单元格
            if (isOpenMergeCell)
            {
                bool isPrevColumnHasSameFormID = IsSameData(fieldName, e.VisibleIndex, e.VisibleIndex - 1);
                bool isNextColumnHasSameFormID = IsSameData(fieldName, e.VisibleIndex, e.VisibleIndex + 1);
                if (Grid.GetRowLevel(e.VisibleIndex) != Grid.GroupCount) return;
                List<int> num = new List<int>();
                if (notMergeNumbers != null)
                    num.AddRange(notMergeNumbers);
                for (int i = e.Row.Cells.Count - 1; i >= 0; i--)
                {
                    if (!(num != null && num.Count > 0 && num.Contains(i)))
                    {
                        DevExpress.Web.ASPxGridView.Rendering.GridViewTableDataCell dataCell = e.Row.Cells[i] as DevExpress.Web.ASPxGridView.Rendering.GridViewTableDataCell;
                        DevExpress.Web.ASPxGridView.Rendering.GridViewTableCommandCell commandCell = e.Row.Cells[i] as DevExpress.Web.ASPxGridView.Rendering.GridViewTableCommandCell;
                        if (dataCell != null)
                        {
                            MergeCells(dataCell.DataColumn, e.VisibleIndex, dataCell, isNextColumnHasSameFormID, isPrevColumnHasSameFormID);
                        }
                        else if (commandCell != null)
                        {
                            MergeCells(commandCell.Column, e.VisibleIndex, commandCell, isNextColumnHasSameFormID, isPrevColumnHasSameFormID);
                        }
                    }
                }
            }
            #endregion
        }
        #endregion
        #region 合并单元格
        void MergeCells(GridViewCommandColumn column, int visibleIndex, TableCell cell, bool isNextColumnHasSameFormID, bool isPrevColumnHasSameFormID)
        {
            if (isNextColumnHasSameFormID)
                {
                    if (!commandCells.ContainsKey(column))
                    {
                        commandCells[column] = cell;
                    }
                }
                if (isPrevColumnHasSameFormID)
                {
                    ((TableRow)cell.Parent).Cells.Remove(cell);
                    if (commandCells.ContainsKey(column))
                    {
                        TableCell commCell = commandCells[column];
                        if (!cellRowSpans.ContainsKey(commCell))
                        {
                            cellRowSpans[commCell] = 1;
                        }
                        cellRowSpans[commCell] = cellRowSpans[commCell] + 1;
                    }
                }
                if (!isNextColumnHasSameFormID)
                {
                    commandCells.Remove(column);
                }
        }
        void MergeCells(GridViewDataColumn column, int visibleIndex, TableCell cell, bool isNextColumnHasSameFormID, bool isPrevColumnHasSameFormID)
        {
            bool isNextTheSame = IsNextColumnHasSameData(column, visibleIndex);
            if (isNextColumnHasSameFormID && isNextTheSame)
            {
                if (!mergedCells.ContainsKey(column))
                {
                    mergedCells[column] = cell;
                }
            }
            if (isPrevColumnHasSameFormID && IsPrevColumnHasSameData(column, visibleIndex))
            {
                ((TableRow)cell.Parent).Cells.Remove(cell);
                if (mergedCells.ContainsKey(column))
                {
                    TableCell mergedCell = mergedCells[column];
                    if (!cellRowSpans.ContainsKey(mergedCell))
                    {
                        cellRowSpans[mergedCell] = 1;
                    }
                    cellRowSpans[mergedCell] = cellRowSpans[mergedCell] + 1;
                }
            }
            if (!isNextColumnHasSameFormID)
            {
                mergedCells.Remove(column);
            }

        }
        bool IsNextColumnHasSameData(GridViewDataColumn column, int visibleIndex)
        {
            //is it the last visible row
            if (visibleIndex >= Grid.VisibleStartIndex + Grid.VisibleRowCount - 1) return false;
            return IsSameData(column.FieldName, visibleIndex, visibleIndex + 1);
        }
        bool IsPrevColumnHasSameData(GridViewDataColumn column, int visibleIndex)
        {
            ASPxGridView grid = column.Grid;
            //is it the first visible row
            if (visibleIndex <= Grid.VisibleStartIndex) return false;
            return IsSameData(column.FieldName, visibleIndex, visibleIndex - 1);
        }
        bool IsSameData(string fieldName, int visibleIndex1, int visibleIndex2)
        {
            // is it a group row?
            if (Grid.GetRowLevel(visibleIndex2) != Grid.GroupCount) return false;
            return object.Equals(Grid.GetRowValues(visibleIndex1, fieldName), Grid.GetRowValues(visibleIndex2, fieldName));
        }
        #endregion
        #region  多表头
        /// <summary>
        /// 重写表头
        /// </summary>
        /// <param name="targetHeader">目标表头</param>
        /// <param name="newHeaderNames">新表头</param>
        /// <remarks>
        /// 等级#级别#上期结存 件数,重量,比例#本期调入 收购调入 件数,重量,比例#本期发出 车间投料 件数,重量,
        /// 比例#本期发出 产品外销百分比 件数,重量,比例#平均值
        /// </remarks>
        void SplitTableHeader(TableRow targetHeader, string newHeaderNames)
        {
            Table table = targetHeader.Parent as Table;
            table.Rows.RemoveAt(0);
            table.CssClass = "dxgvTable_Office2003_Blue";
            int row = GetRowCount(newHeaderNames);
            int col = GetColCount(newHeaderNames);
            string[,] nameList = ConvertList(newHeaderNames, row, col);
            int RowSpan = 0;
            int ColSpan = 0;
            for (int k = 0; k < row; k++)
            {
                TableRow trow = new TableRow();
                trow.Height = 20;
                string LastFName = "";
                for (int i = 0; i < col; i++)
                {
                    TableCell cell = new TableCell();
                    if (LastFName == nameList[i, k] && k != row - 1)
                    {
                        LastFName = nameList[i, k];
                        continue;
                    }
                    else
                    {
                        LastFName = nameList[i, k];
                    }
                    int bFlag = IsVisible(nameList, k, i, LastFName);
                    switch (bFlag)
                    {
                        case 0:
                            break;
                        case 1:
                            RowSpan = GetSpanRowCount(nameList, row, k, i);
                            ColSpan = GetSpanColCount(nameList, row, col, k, i);
                            cell = new TableCell();
                            cell.RowSpan = RowSpan;
                            cell.ColumnSpan = ColSpan;
                            cell.CssClass = "dxgvHeader_Office2003_Blue";
                            cell.Text = LastFName;
                            cell.BorderStyle = BorderStyle.Solid;
                            cell.BorderWidth = Unit.Pixel(0);
                            cell.Style.Add(HtmlTextWriterStyle.TextAlign, "center");
                            cell.Style.Add(HtmlTextWriterStyle.BorderCollapse, "collapse");
                            cell.Style.Add(HtmlTextWriterStyle.BorderCollapse, "separate");
                            cell.Style["BORDER-RIGHT-WIDTH"] = "1px";
                            cell.Style["BORDER-BOTTOM-WIDTH"] = "1px";
                            trow.Cells.Add(cell);
                            break;
                        case -1:
                            string[] EndColName = LastFName.Split(new char[] { ',' });
                            foreach (string eName in EndColName)
                            {
                                cell = new TableCell();
                                cell.Text = eName;
                                cell.BorderStyle = BorderStyle.Solid;
                                cell.BorderWidth = Unit.Pixel(0);
                                cell.CssClass = "dxgvHeader_Office2003_Blue";
                                cell.Style.Add(HtmlTextWriterStyle.TextAlign, "center");
                                cell.Style.Add(HtmlTextWriterStyle.BorderCollapse, "collapse");
                                cell.Style.Add(HtmlTextWriterStyle.BorderCollapse, "separate");
                                cell.Style["BORDER-RIGHT-WIDTH"] = "1px";
                                cell.Style["BORDER-BOTTOM-WIDTH"] = "1px";
                                trow.Cells.Add(cell);
                            }
                            break;
                    }
                }
                if (k != row - 1)
                {//不是起始行,加入新行标签
                    //cell.Text = cell.Text + "</th></tr><tr>";
                }
                table.Rows.AddAt(k, trow);
            }
        }
        /**/
        /// <summary>
        /// 如果上一行已经输出和当前内容相同的列头,则不显示
        /// </summary>
        /// <param name="ColumnList">表头集合</param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="colIndex">列索引</param>
        /// <returns>1:显示,-1:含','分隔符,0:不显示</returns>
        private int IsVisible(string[,] ColumnList, int rowIndex, int colIndex, string CurrName)
        {
            if (rowIndex != 0)
            {
                if (ColumnList[colIndex, rowIndex - 1] == CurrName)
                {
                    return 0;
                }
                else
                {
                    if (ColumnList[colIndex, rowIndex].Contains(","))
                    {
                        return -1;
                    }
                    else
                    {
                        return 1;
                    }
                }
            }
            return 1;
        }
        /**/
        /// <summary>
        /// 取得和当前索引行及列对应的下级的内容所跨的行数
        /// </summary>
        /// <param name="ColumnList">表头集合</param>
        /// <param name="row">行数</param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="colIndex">列索引</param>
        /// <returns>行数</returns>
        private int GetSpanRowCount(string[,] ColumnList, int row, int rowIndex, int colIndex)
        {
            string LastName = "";
            int RowSpan = 1;
            for (int k = rowIndex; k < row; k++)
            {
                if (ColumnList[colIndex, k] == LastName)
                {
                    RowSpan++;
                }
                else
                {
                    LastName = ColumnList[colIndex, k];
                }
            }
            return RowSpan;
        }
        /**/
        /// <summary>
        /// 取得和当前索引行及列对应的下级的内容所跨的列数
        /// </summary>
        /// <param name="ColumnList">表头集合</param>
        /// <param name="row">行数</param>
        /// <param name="col">列数</param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="colIndex">列索引</param>
        /// <returns>列数</returns>
        private int GetSpanColCount(string[,] ColumnList, int row, int col, int rowIndex, int colIndex)
        {
            string LastName = ColumnList[colIndex, rowIndex];
            int ColSpan = ColumnList[colIndex, row - 1].Split(new char[] { ',' }).Length;
            ColSpan = ColSpan == 1 ? 0 : ColSpan;
            for (int i = colIndex + 1; i < col; i++)
            {
                if (ColumnList[i, rowIndex] == LastName)
                {
                    ColSpan += ColumnList[i, row - 1].Split(new char[] { ',' }).Length;
                }
                else
                {
                    LastName = ColumnList[i, rowIndex];
                    break;
                }
            }
            return ColSpan;
        }
        /**/
        /// <summary>
        /// 将已定义的表头保存到数组
        /// </summary>
        /// <param name="newHeaders">新表头</param>
        /// <param name="row">行数</param>
        /// <param name="col">列数</param>
        /// <returns>表头数组</returns>
        private string[,] ConvertList(string newHeaders, int row, int col)
        {
            string[] ColumnNames = newHeaders.Split(new char[] { '#' });
            string[,] news = new string[col, row];
            string Name = "";
            for (int i = 0; i < col; i++)
            {
                string[] CurrColNames = ColumnNames[i].ToString().Split(new char[] { ' ' });
                for (int k = 0; k < row; k++)
                {
                    if (CurrColNames.Length - 1 >= k)
                    {
                        if (CurrColNames[k].Contains(","))
                        {
                            if (CurrColNames.Length != row)
                            {
                                if (Name == "")
                                {
                                    news[i, k] = news[i, k - 1];
                                    Name = CurrColNames[k].ToString();
                                }
                                else
                                {
                                    news[i, k + 1] = Name;
                                    Name = "";
                                }
                            }
                            else
                            {
                                news[i, k] = CurrColNames[k].ToString();
                            }
                        }
                        else
                        {
                            news[i, k] = CurrColNames[k].ToString();
                        }
                    }
                    else
                    {
                        if (Name == "")
                        {
                            news[i, k] = news[i, k - 1];
                        }
                        else
                        {
                            news[i, k] = Name;
                            Name = "";
                        }
                    }
                }
            }
            return news;
        }
        /**/
        /// <summary>
        /// 取得复合表头的行数
        /// </summary>
        /// <param name="newHeaders">新表头</param>
        /// <returns>行数</returns>
        private int GetRowCount(string newHeaders)
        {
            string[] ColumnNames = newHeaders.Split(new char[] { '#' });
            int Count = 0;
            foreach (string name in ColumnNames)
            {
                int TempCount = name.Split(new char[] { ' ' }).Length;
                if (TempCount > Count)
                    Count = TempCount;
            }
            return Count;
        }
        /**/
        /// <summary>
        /// 取得复合表头的列数
        /// </summary>
        /// <param name="newHeaders">新表头</param>
        /// <returns>列数</returns>
        private int GetColCount(string newHeaders)
        {
            return newHeaders.Split(new char[] { '#' }).Length;
        }
        #endregion
        #region ASPxGridView列操作
        //#region 创建GridViewDataColumn列
        //public static GridViewDataColumn CreateDataColumn(string caption, string fieldName, int width, bool visible, int visibleIndex, DevExpress.Data.ColumnSortOrder sortOrder, ColumnFilterMode columnFilterMode, DevExpress.Web.ASPxClasses.DefaultBoolean autoFilter, DevExpress.Web.ASPxClasses.DefaultBoolean headerFilter)
        //{
        //    GridViewDataTextColumn column = new GridViewDataTextColumn();
        //    column.Caption = caption;
        //    column.FieldName = fieldName;
        //    if (width != 0) column.Width = width;
        //    column.Visible = visible;
        //    column.VisibleIndex = visibleIndex;
        //    column.SortOrder = sortOrder;
        //    column.Settings.AllowAutoFilter = autoFilter;
        //    column.Settings.AllowHeaderFilter = headerFilter;
        //    column.Settings.FilterMode = columnFilterMode;
        //    return column;
        //}
        //#endregion
        #region 显示隐藏列
        public void ChangeColumsDisplay(string[] displayFields, bool display)
        {
            if (displayFields != null && displayFields.Length > 0)
            {
                foreach (string item in displayFields)
                {
                    Grid.Columns[item].Visible = display;
                }
            }
        }
        #endregion
        #region 改变列的显示索引
        public void ChangeColumnsVisibleIndex(string[] fields, int[] newVisibleIndex)
        {
            if (fields != null && fields.Length > 0)
            {
                for (int i = 0; i < fields.Length; i++)
                {
                    Grid.Columns[fields[i]].VisibleIndex = newVisibleIndex[i];
                }
            }
        }
        #endregion
        #region 改变列标题
        public void ChangeColumnsCaption(string[] fields, string[] newCaption)
        {
            if (fields != null && fields.Length > 0)
            {
                for (int i = 0; i < fields.Length; i++)
                {
                    Grid.Columns[fields[i]].Caption = newCaption[i];
                }
            }
        }
        #endregion
        #endregion
    }
}

使用举例:根据不同的条件显示自定义的多表头、字段及合并单元格

 protected void Page_Load(object sender, EventArgs e)
    {
        InitGrid();
        InitGridDisplayColumns();//此方法在GridView绑定数据之前扔需执行
    }

 private void InitGrid()
    {
        string header = "选择#序号#设备位号#设备名称#检修<br/>类别#检修内容 序号,内容#主要备件及材料 名称,规格,材质,数量,单位#施工单位#项目负责人 施工单位,生产车间,配合部门#完成情况 开工,完工#计划<br/>检修<br/>时间#备注";
        string fieldName = "JXBH";
        bool isOpenMergeCell = true;
        bool isOpenMutiHeader = true;
        int[] num = null;
        switch (XMIndex)
        {
            case 1://工艺
                header = "选择#序号#工段#工艺项目内容 序号,内容#施工单位#项目负责人 生产车间,配合部门#备注";
                break;
            case 2://容器
                header = "选择#序号#容器编号#容器名称#类别#内径#材质#壁厚#长度#操作压力#操作温度#介质#安全状况等级#到期检验日期#计划安排检验时间#重点检验部位#备注";
                isOpenMergeCell = false;
                break;
            case 3://管道
                header = "选择#序号#管道编号#管线号#管道起点#管道止点#公称直径#公称壁厚#累计长度#工作压力#工作温度#材质#级别#介质#近期检验日期#下次检验日期#安全状况等级#重点检验部位#备注";
                isOpenMergeCell = false;
                break;
            case 5://防腐保温
                header = "选择#序号#位号#名称#工段#具体内容 序号,内容,数量#备注";
                break;
            default:
                num = new int[] { 7, 8, 9, 10, 11 };
                break;
        }
        ASPxGridViewHelper helper = new ASPxGridViewHelper(this.GV_JH, fieldName, num, header, isOpenMutiHeader, isOpenMergeCell);
    }
    private void InitGridDisplayColumns()
    {
        string[] hidenFields = null;
        int[] newNums = new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
        switch (XMIndex)
        {
            case 1://工艺
                hidenFields = new string[] { "SBWH", "JXLB", "BJBM", "BJMC", "BJGG", "BJTH", "BJCZ", "BJSL", "SLDW", "SGDWFZR", "JHKG", "JHWG", "JHJXSJ" };
                break;
            case 2://容器
                hidenFields = new string[] { "JXLB", "JXNRH", "JXNR", "SCCJFZR", "JHJXSJ" };
                newNums = new int[] { 2, 3, 4, 5, 6, 7, 10, 11, 8, 9, 12, 13, 14, 15, 16, 19, 17, 18, 20, 21 };
                break;
            case 3://管道
                hidenFields = new string[] { "JXLB", "JXNRH", "JXNR" };
                newNums = new int[] { 3, 2, 4, 5, 6, 7, 9, 11, 10, 14, 12, 13, 16, 19, 8, 20, 17, 18, 15, 21 };
                break;
            case 5://防腐保温
                hidenFields = new string[] { "JXLB", "BJBM", "BJGG", "BJTH", "BJCZ", "SLDW", "SGDW", "SGDWFZR", "SCCJFZR", "PHBMFZR", "JHKG", "JHWG", "JHJXSJ" };
                newNums = new int[] { 2, 3, 8, 5, 6, 7, 4, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
                break;
            default:
                hidenFields = new string[] { "BJBM", "BJTH" };
                break;
        }
        ASPxGridViewHelper helper = new ASPxGridViewHelper(this.GV_JH);
        string[] fields = new string[] { "SBWH", "SBMC", "JXLB", "JXNRH", "JXNR", "BJBM", "BJMC", "BJGG", "BJTH", "BJCZ", "BJSL", "SLDW", "SGDW", "SGDWFZR", "SCCJFZR", "PHBMFZR", "JHKG", "JHWG", "JHJXSJ", "BZ" };
        helper.ChangeColumsDisplay(fields, true);
        helper.ChangeColumnsVisibleIndex(fields, newNums);
        helper.ChangeColumsDisplay(hidenFields, false);
    }

部分代码来源互联网

实现效果图:


抱歉!评论已关闭.