ASP.NET: Rotated / Pivoted GridView

by Jon 12/6/2007 11:17:00 AM

I needed to rotate the content of my GridView control. I was databinding using business objects. Why is there no boolean pivot switch?

So I made my own control that inherits GridView. This is just a C# file; to use it, put it in the App_Code folder, and add <%@ Register Namespace="CustomControls" TagPrefix="Custom" %> to the ASPX file.

Not sure if it's buggy or not but it currently passes initial tests.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

namespace CustomControls {
    public partial class PivotDataGrid : System.Web.UI.WebControls.DataGrid
    {
        public PivotDataGrid() : base() { }

        public enum Pivot
        {
            /// <summary>
            /// Rotates the grid by rotating the data source in a replacement matrix. (not implemented)
            /// </summary>
            PreRender,
            /// <summary>
            /// Rotates the grid by converting the output to XML and rotating the cells.
            /// </summary>
            PostRender
        }

        private Pivot _PivotMode = Pivot.PostRender;
        public Pivot PivotMode
        {
            get { return _PivotMode; }
            set { _PivotMode = value; }
        }
        protected override void Render(HtmlTextWriter writer)
        {
            switch (PivotMode)
            {
                case Pivot.PostRender:
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    System.IO.StringWriter sw = new System.IO.StringWriter(sb);
                    HtmlTextWriter htw = new HtmlTextWriter(sw);
                    base.Render(htw);
                    System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
                    xDoc.LoadXml(sb.ToString().Replace("&nbsp;", "&#160;"));
                    System.Xml.XmlDocument xDoc2 = new System.Xml.XmlDocument();
                    xDoc2.LoadXml(xDoc.OuterXml);
                    XmlNodeList rowNodes = xDoc.SelectNodes("//tr");
                    XmlNode trParent = null;
                    if (rowNodes.Count > 0) trParent = rowNodes[0].ParentNode;
                    rowNodes = xDoc2.SelectNodes("//tr");
                    XmlNode trParent2 = null;
                    if (rowNodes.Count > 0) trParent2 = rowNodes[0].ParentNode;
                    for (int i = rowNodes.Count - 1; i >= 0; i--)
                    {
                        rowNodes[i].ParentNode.RemoveChild(rowNodes[i]);
                    }

                    RotateRows(trParent, trParent2, xDoc2);
                    writer.Write(xDoc2.OuterXml);

                    break;
                default:
                    base.Render(writer);
                    return;
            }
        }

        protected override void DataBind(bool raiseOnDataBinding)
        {
            switch (PivotMode)
            {
                case Pivot.PreRender:
                    RotateDataSource();
                    base.DataBind(raiseOnDataBinding);
                    break;
                case Pivot.PostRender:
                    base.DataBind(raiseOnDataBinding);
                    break;
            }
        }

        void RotateDataSource()
        {
            //object src = base.DataSource;
            //System.Reflection.PropertyInfo[] srcProps = src.GetType().GetProperties(System.Reflection.BindingFlags.GetProperty);
            //Dictionary<string, Dictionary<string, object>> newSource = new Dictionary<string, object>();
            //DataKeyArray keys = this.DataKeys;
            throw new NotImplementedException("PivotMode of Pivot.PreRender has not yet been implemented.");
        }

        //Cell[,] RowsToCells
        void RotateRows(XmlNode sourceParentNode, XmlNode targetParentNode, // bool rotate
            XmlDocument targetContext)
        {
            bool rotate = true;
            XmlNodeList trNodes = sourceParentNode.SelectNodes("tr");
            int rowLen = trNodes.Count;
            int colLen = 0;
            if (rowLen > 0) colLen = trNodes[0].SelectNodes("td").Count;
            Cell[,] cells;
            List<XmlAttribute>[] rowAttribs = new List<XmlAttribute>[rowLen];
            if (!rotate) cells = new Cell[rowLen, colLen];
            else cells = new Cell[colLen, rowLen];
            for (int r = 0; r < rowLen; r++)
            {
                rowAttribs[r] = new List<XmlAttribute>();
                for (int a = 0; a < trNodes[r].Attributes.Count; a++)
                {
                    XmlAttribute attrib = targetContext.CreateAttribute(trNodes[r].Attributes[a].Name);
                    attrib.Value = trNodes[r].Attributes[a].Value;
                    rowAttribs[r].Add(attrib);
                }

                for (int c = 0; c < colLen; c++)
                {
                    XmlNode tdNode = trNodes[r].SelectNodes("td")[c];
                    Cell cell = new Cell();
                    //cell.Attributes = tdNode[c].Attributes;
                    cell.Attributes = new List<XmlAttribute>();
                    for (int a = 0; a < tdNode.Attributes.Count; a++)
                    {
                        XmlAttribute attrib = targetContext.CreateAttribute(tdNode.Attributes[a].Name);
                        attrib.Value = tdNode.Attributes[a].Value;
                        cell.Attributes.Add(attrib);
                    }
                    cell.InnerXml = trNodes[r].SelectNodes("td")[c].InnerXml;
                    if (rotate) cells[c, r] = cell;
                    else cells[r, c] = cell;
                }
            }
            //return cells;
            for (int cR = cells.GetLowerBound(0); cR <= cells.GetUpperBound(0); cR++)
            {
                XmlNode rowNode = targetContext.CreateElement("tr");
                for (int cC = cells.GetLowerBound(1); cC <= cells.GetUpperBound(1); cC++)
                {
                    Cell cell = cells[cR, cC];
                    XmlNode colNode = targetContext.CreateElement("td");
                    for (int a = 0; a < cell.Attributes.Count; a++)
                    {
                        colNode.Attributes.Append(cell.Attributes[a]);
                    }
                    colNode.InnerXml = cell.InnerXml;
                    if (rotate)
                        for (int rA = 0; rA < rowAttribs[cC].Count; rA++)
                        {
                            if (colNode.Attributes[rowAttribs[cC][rA].Name] != null)
                            {
                                colNode.Attributes[rowAttribs[cC][rA].Name].Value = rowAttribs[cC][rA].Value;
                            }
                            else
                            {
                                XmlAttribute newAttrib = targetContext.CreateAttribute(rowAttribs[cC][rA].Name);
                                newAttrib.Value = rowAttribs[cC][rA].Value;
                                colNode.Attributes.Append(newAttrib);
                            }
                        }
                    rowNode.AppendChild(colNode);
                }
                if (!rotate)
                    for (int rA = 0; rA < rowAttribs[cR].Count; rA++)
                    {
                        rowNode.Attributes.Append(rowAttribs[cR][rA]);
                    }
                targetParentNode.AppendChild(rowNode);
            }
        }

        class Cell
        {
            private List<XmlAttribute> _Attributes;

            public List<XmlAttribute> Attributes
            {
                get { return _Attributes; }
                set { _Attributes = value; }
            }

            private string _InnerXml;

            public string InnerXml
            {
                get { return _InnerXml; }
                set { _InnerXml = value; }
            }

        }
    }
}

kick it on DotNetKicks.com

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Open Source | Software Development | Web Development

Related posts

Add comment


(Will show your Gravatar icon)  

  Country flag





Live preview

10/7/2008 9:31:31 PM


 

Powered by BlogEngine.NET 1.2.0.0
Theme by Mads Kristensen

About the author

Jon Davis Jon Davis (aka "stimpy77") is a software and web developer by day and a software and web enthusiast (geek) by night. He was recently a senior web engineer for the enthusiast division of a major magazine publishing company for nearly two years. He has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."
 
Jon is currently engaged in a short-term ASP.NET contract and is available for hire for short-term or permanent work in Phoenix or via telecommute.
E-mail me Send mail

Calendar

<<  October 2008  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Pages

    Recent comments

    Authors

    Tags

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008

    Sign in