Blog

posts tagged with web

Windows 8 Javascript Tips - TypeScript support

0 Comments
By Fons Sonnemans, 9-10-2012

Microsoft announced TypeScript last week. TypeScript is a superset of JavaScript that combines type checking and static analysis, explicit interfaces, and best practices into a single language and compiler. It is an open source programming language developed by Microsoft. If you haven't investigated yet make sure you do. The related links below might help you.

What Microsoft didn't do (yet) is add TypeScript support to JavaScript Windows Store apps. In this blog I will explain how to add this support to Visual Studio so you can use TypeScript in all your Windows 8 apps.

Step 1 - Install TypeScript

You can install TypeScript for Visual Studio 2012 using an MSI setup which you can download here. Make sure you first close all Visual Studio instances to avoid installation problems.

Step 2 - Install Web Essentials 2012

The latest version of Web Essentials 2012 extension adds support for TypeScript preview and compilation. When you save a TypeScript (.ts) file it will be compiled into a JavaScript (.js) file. So make sure you install it using the Visual Studio menu Tools, Extensions and Updates. If you already installed it make sure you update it to the latest version.

Step 3 - Add TypeScript ItemTemplate

If you try to add a TypeScript item to the 'js' folder you will see that there is no TypeScript template available. The setup from Microsoft did not (yet) add this template to Visual Studio. My solution for this problem was quite easy. I copied the following file 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\msfz1qy5.oca\~IC\IT\CSharp\1033\f.zip' to my '\My Documents\Visual Studio 2012\Templates\ItemTemplates\JavaScript' folder. I also renamed the file to TypeScript.zip. Next I opened the zip file and edited the 'f.vstemplate' file. In the file I changed the ProjectType element from CSharp to JavaScript.

To make life easy you can download my TypeScript.zip file so you don't have to repeat my steps. Make sure you place it in the right ItemTemplate folder.

Step 4 - Create a JavaScript Project

This step is really easy. Just create a Project in Visual studio using one of the JavaScript Windows Store templates.

Step 5 - Add TypeScript item

When you add a new Item to the 'js' folder you can now select the TypeScript template.

The preview feature of Web Essentials 2012 shows you how your TypeScript file is compiled into JavaScript.

You should also change the Package Action of the Demo.ts file to 'None'. Otherwise the file will also be included in the APPX file which will make it larger. Only the Demo.js file is required.

TypeScript options

Web Essentials 2012 also supports some options which you might want to change. I only want to compile my TypeScripts on Build and not on every Save. You can also turn preview off but that didn't work on my computer. I hope they will fix it.

Closure

Now it is up to you to write your own TypeScript files. I love the ability to write clean OO code using: classes, interfaces, modules (namespaces), type annotations, compile time type checking and arrow functions (similar to Lambda Expression in C#). I hope this blog will help you write great Windows Store apps.

Cheers,

Fons

Related Links

Fix the ASP.NET Themes with IE8’s X-UA-Compatible header problem

0 Comments
By Fons Sonnemans, 26-9-2008

If you’ve got a page that doesn’t render correctly in IE8’s new standards mode, you can add a meta tag to the page which requests that IE8 render it in IE7 mode. IE8 only recognizes the X-UA-Compatible header if it’s the first META tag, appearing immediately after the tag.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Problem

The ASP.NET Theme system writes out the theme CSS reference immediately after the <HEAD> tag. This makes it impossible to set the X-UA-Compatible header or to use Stylesheets in your theme folder.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>

The Solution

To fix this problem I have added an implementation for the Application_PreRequestHandlerExecute event in the Global.asax. This method will sort the controls inside the header. It places the X-UA-Compatible metatag on top. I use an anonymous method which is subscribed to the PreRenderComplete event of page. This method uses LINQ to find the metatag. Then removes it from the header and add it again on top.

void Application_PreRequestHandlerExecute(object src, EventArgs e) {
    Page p = this.Context.Handler as Page;
    if (p != null) {
        p.PreRenderComplete += (sender, ee) => {
            // I can't use p, it has no Header set (strange), use sender instead
            Page page = sender as Page; 
            if (page.Header != null) {
                // Find the Compatible Meta tag
                var ctrl = page.Header.Controls.Cast<Control>().FirstOrDefault(
                    c => c is HtmlMeta && ((HtmlMeta)c).HttpEquiv == "X-UA-Compatible");

                // If found remove it and add it on top
                if (ctrl != null) {
                    page.Header.Controls.Remove(ctrl);
                    page.Header.Controls.AddAt(0, ctrl);
                }
            }
        };
    }
}

This results in the correct HTML.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1"> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <link href="App_Themes/Default/Stylesheet.css" type="text/css" rel="stylesheet" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="shortcut icon" href="favicon.ico" /> <title>Test</title> </head> <body>[...]</body></html>
Tags: Web, ASP.NET

ASP.NET ViewStateParameter

0 Comments
By Fons Sonnemans, 30-5-2007

I like the ASP.NET 2.0 DataSource controls. They are very flexible and easy to use. It has some great parameters like SessionParameter and ControlParameter. It doesn't have a ViewStateParameter. I have written it myself to fill this gap.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace ClassLibrary1 {

    public class ViewStateParameter : Parameter {

        private String _key;

        public String Key {
            get {
                return _key;
            }
            set {
                _key = value;
            }
        }

        protected override object Evaluate(HttpContext context, Control control) {
            Type t = control.Page.GetType();
            System.Reflection.PropertyInfo pi = t.GetProperty("ViewState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            StateBag pageViewState = pi.GetValue(control.Page, null) as StateBag;
            return pageViewState[Key];
        }
    }
}

My solution uses Reflection to retrieve the ViewState out of the Page. You will need FullTrust to use the code, bummer.

Download the source + sample website here.
Tags: Web, ASP.NET

Objectmap.nl

0 Comments
By Fons Sonnemans, 5-11-2006

Today we have published a new website called Objectmap. It is for now in Dutch only. It uses Google Maps to display objects on a map. Registered users can add the objects to the system. A script is generated for each object which can be used to display the map. When you copy&paste this script into your own webpage you can display the map in a pop-up window or IFrame.


Click here for a pop-up window demo.

A complete explanation how to add objects and how to make them visible on your own site can be found here. The website is still in BETA. You can send a mail to info@objectmap.nl to request a beta account.

Tags: Web, ASP.NET

Playing with Google Maps

0 Comments
By Fons Sonnemans, 22-9-2006

I have developed a small website which uses Google Maps to prepare myself for a new project. Have a look here.

I have used GoogleMaps.Subgurim.NET to simplify things. This is an ASP.NET control which encapsulates the Google Maps API. Their site is in Spanish but with Babel Fish you can translate it to English.

The full C# source of the website can be downloaded from here.

Tags: Web, ASP.NET

Playing with Ajax (Atlas)

0 Comments
By Fons Sonnemans, 27-3-2006

I have finally found some time to play with Ajax. I have built some simple Grid/Detail pages which are place inside an UpdatePanel. This server centric model is really easy and powerful. I have never really liked the user experience of web applications. Atlas will changes this and will make the WEB even more popular.

Have a look at the result demo site. I use the ObjectDataSource to bind to Buffy.NET BusinessObjects. It's so easy.

Tags: Web, ASP.NET

Move to ASP.NET 2.0

0 Comments
By Fons Sonnemans, 2-3-2006

I have finally rewritten this website to ASP.NET 2.0. It was really a good learning experience. You only learn it by doing it. I have tried to use the new features like:

It wasn't really difficult to do. Microsoft really kept their promise that 70% of the code could disappear. ASP.NET 2.0 rocks. I'm planning to add some extra features soon, like: WebParts, Health Monitoring, other new controls, comments on blog posts, a new stylesheet and a new logo.

Update 2006-sept-25: Added Google Sitemaps, Control Adapters and UrlRewritingNet.

Tags: Web, ASP.NET

Websites using my CMS are online

0 Comments
By Fons Sonnemans, 20-10-2005

I have written a small content management system using ASP.NET. Sjef de Corte has implemented 3 websites with it. Well done Sjef!

Tags: Web, ASP.NET

InitialFocus on a ASP.NET WebForm

0 Comments
By Fons Sonnemans, 28-4-2004

Download InitialFocusDemo.zip

Introduction

The PageUtil class has a static method SetInitialFocus(control) which can be used to generate a JavaScript for an ASP.NET page (WebForm), which sets the focus on a (given) control.

        private voidPage_Load(objectsender, System.EventArgs e)
        {
            // Set the InitialFocus on TextBox1
            ReflectionIT.Web.PageUtil.SetInitialFocus(TextBox1);
        }

TextBox1: 

PageUtil Class

using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ReflectionIT.Web {
    /// <summary>
    /// Utility class for a ASP.NET page
    ///
    /// Be sure to notice that this code is provided as a technology sample,
    /// 'as is' and no warranties are made by the author.
    ///
    /// For questions and comments: Fons.Sonnemans@reflectionit.nl
    ///
    /// </summary>
    public class PageUtil {

        /// <summary>
        /// Set the InitialFocus to the given control. Only works when JavaScript is supported.
        /// </summary>
        /// <param name="control">Control to set the InitialFocus on.</param>
        publicstaticvoid SetInitialFocus(Control control){
            // Postpone setting the InitialFocus to the PreRender event of the control.
            // The control might not yet have a Page property, in PreRender it always has!
            control.PreRender += new EventHandler(InitialFocusControl_PreRender);
        }

        /// <summary>
        /// Set the InitialFocus to the control that notified this EventHandler (sender)
        /// </summary>
        /// <param name="sender">The source of the event. </param>
        /// <param name="e">An EventArgs that contains the event data. </param>
        privatestaticvoid InitialFocusControl_PreRender(object sender, EventArgs e){
            Control control=senderas Control;

            if(control.Page == null){
                thrownew ArgumentException(
                    "The Control must be added to a Page before you can set the IntialFocus to it.");
            }
            if(control.Page.Request.Browser.JavaScript ==true) {
                // Create JavaScript
                StringBuilder s =new StringBuilder();
                s.Append("\n<SCRIPT LANGUAGE='JavaScript'>\n");
                s.Append("<!--\n");
                s.Append("function SetInitialFocus()\n");
                s.Append("{\n");
                s.Append(" document.");

                // Find the Form
                Control p =control.Parent;
                while(!(p is System.Web.UI.HtmlControls.HtmlForm))
                    p = p.Parent;
                s.Append(p.ClientID);

                s.Append("['");
                s.Append(control.UniqueID);

                // Set Focus on the selected item of a RadioButtonList
                RadioButtonList rbl= controlas RadioButtonList;
                if(rbl!= null){
                    stringsuffix ="_0";
                    int t = 0;
                    foreach(ListItem liinrbl.Items){
                        if(li.Selected) {
                            suffix= "_"+ t.ToString();
                            break;
                        }
                        t++;
                    }
                    s.Append(suffix);
                }

                // Set Focus on the first item of a CheckBoxList
                if(controlis CheckBoxList){
                    s.Append("_0");
                }

                s.Append("'].focus();\n");
                s.Append("}\n");

                if(control.Page.SmartNavigation)
                    s.Append("window.setTimeout(SetInitialFocus, 500);\n");
                else
                    s.Append("window.onload = SetInitialFocus;\n");

                s.Append("// -->\n");
                s.Append("</SCRIPT>");

                // Register Client Script
                control.Page.RegisterClientScriptBlock("InitialFocus", s.ToString());
            }
        }
    }
}

Example

Textbox1 has the focus after the page is loaded.

 WebForm1.aspx

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="InitialFocusDemo.WebForm1"smartNavigation="False"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    <HEAD>
        <metacontent="Microsoft Visual Studio 7.0"name="GENERATOR">
        <metacontent="C#"name="CODE_LANGUAGE">
        <metacontent="JavaScript (ECMAScript)"name="vs_defaultClientScript">
        <metacontent="http://schemas.microsoft.com/intellisense/ie5"name="vs_targetSchema">
    </HEAD>
    <body>
        <formid="Form1"method="post"runat="server">
            <table>
                <tr>
                    <td>
                        <asp:labelid="Label1"runat="server">Label</asp:label>
                    </td>
                    <td>
                        <asp:textboxid="TextBox1"runat="server"></asp:textbox>
                    </td>
                </tr>
                <tr>
                    <td>
                        <asp:labelid="Label2"runat="server">Label</asp:label>
                    </td>
                    <td>
                        <asp:textboxid="TextBox2"runat="server"></asp:textbox>
                    </td>
                </tr>
                <tr>
                    <td>
                    </td>
                    <td>
                        <asp:Button id="Button1"runat="server" Text="Button"></asp:Button>
                    </td>
                </tr>
            </table
        </form>
    </body>
</HTML>

 WebForm1.aspx.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace InitialFocusDemo
{
    /// <summary>
    /// Summary description for WebForm1.
    /// </summary>
    public class WebForm1: System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.Label Label1;
        protected System.Web.UI.WebControls.Label Label2;
        protected System.Web.UI.WebControls.TextBox TextBox1;
        protected System.Web.UI.WebControls.Button Button1; 
        protected System.Web.UI.WebControls.TextBox TextBox2;
    
        public WebForm1()
        {
            Page.Init +=new System.EventHandler(Page_Init);
        }

        privatevoid Page_Load(objectsender, System.EventArgs e)
        {
            // Set the InitialFocus on TextBox1
            ReflectionIT.Web.PageUtil.SetInitialFocus(TextBox1);
        }

        privatevoid Page_Init(objectsender, EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
        }

        #region Web Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        privatevoid InitializeComponent()
        {    
            this.Load +=new System.EventHandler(this.Page_Load);

        }
        #endregion

    }
}

Thanks to:

  • Philip Quirke who reported a bug in an earlier version. I used the controls 'UniqueID' property instead of 'ClientID' in the SetInitialFocus() method.
  • S Patil who reported that it didn't work with Netscape 4.7x browser. I have therfore changed the JavaScript.
  • Scott Dinwiddie who reported the SmartNavigation problem.
  • Waylon Campbell who reported the RadioButtonList problem.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

Tags: Web, ASP.NET

ASP.NET DataIslandGrid Control

0 Comments
By Fons Sonnemans, 1-1-2003

Download DataIslandGrid.zip

Introduction

The standard ASP.NET DataGrid control is a great control. You can use it for many things, it even supports Paging and Column Sorting. Those last two option although work using postbacks to the server.

Internet Explorer 5.0 (and higher) support XML Client-side Data-Binding. This is a powerful DHTML feature which is not used in the .NET Framework. It allows.

The DataIslandGrid control is an ASP.NET grid which is bound to a DataTable in a DataSet. The DataSet is serialized and rendered to an Xml DataIsland. The Grid uses Tabular Data-Binding to the Xml DataIsland. This makes it possible to support client-side Column Sorting and Paging. The Column Sorting is implemented using a JavaScript and a StyleSheet in a second Xml DataIsland.


Example

The following grid is a DataIslandGrid which is bound to the Authors table of the SQLServer pubs database.

IDFirstnameLastnameAddressCity
<< < > >>
172-32-1176
Johnson
White
abc
Stein
213-46-8915
Marjorie
Green
abc
Oakland
238-95-7766
Rony
Carson
abc
Berkeley
267-41-2394
Michael
O'Leary
abc
San Jose
274-80-9391
Dean
Straight
abc
Oakland
341-22-1782
Meander
Smith
abc
Lawrence
409-56-7008
Abrahamfdfs
Bennett
abc
Berkeley
427-17-2319
Ann
Dull
abc
Palo Alto
472-27-2349
Burt
Gringlesby
abc
Covelo
486-29-1786
Charlene
Locksley
abc
San Francisco

The Html of this page must have redirective to the DataIslandGridProject. Then you can add the DataIslandGrid control to the Page. The best way to do this is by adding the assembly to your Toolbox. You then can drag&drop the DataIslandGrid from your Toolbox onto your Page.

<%@ Register TagPrefix="rit" Namespace="ReflectionIT.Web.UI.WebControls"  Assembly="DataIslandGridProject"%>
.
.
<rit:DataIslandGrid id="DataIslandGrid1"runat="server" CellSpacing="0" BorderWidth="1px"
AllowSorting="true" CssClass="clsTest"width="80%" BorderColor="WhiteSmoke">
   <rit:BoundColumn CssClass="clsColumnID" Width="120px" DataField="au_id" HeaderText="ID"/>
   <rit:BoundColumn DataField="au_fname" HeaderText="Firstname"></rit:BoundColumn>
   <rit:BoundColumn DataField="au_lname" HeaderText="Lastname"></rit:BoundColumn>
   <rit:BoundColumn DataField="address" HeaderText="Address"></rit:BoundColumn>
   <rit:BoundColumn DataField="city" HeaderText="City"></rit:BoundColumn>
</rit:DataIslandGrid>
.
.

You add Columns to the datagrid using the BoundColumn Collection Editor.

The following code binds the DataGrid to the Authors table. I have converted the SQLServer table to an MS Access database to make testing easier.

public class WebForm1: System.Web.UI.Page
{
    protected ReflectionIT.Web.UI.WebControls.DataIslandGrid DataIslandGrid1;

    privatevoid Page_Load(objectsender, System.EventArgs e)
    {
        stringconnectString=string.Format(
         @"Provider=Microsoft.Jet.OLEDB.4.0;Password=;User ID=Admin;Data Source={0};",
         Server.MapPath("pubs.mdb"));

        using(OleDbConnection con=new OleDbConnection(connectString)){
            con.Open();
            using(OleDbCommand cmd=new OleDbCommand("select * from Authors",con)){
                OleDbDataAdapter da= new OleDbDataAdapter(cmd);
                DataSet ds= new DataSet();
                da.Fill(ds);

                // Bind the DataGrid
                DataIslandGrid1.DataSet =ds;
            }
        }
    }
}

DataIslandGrid Control

The DataIslandGrid class is a WebControl with a lot of attributes. The ParseChilderenAttribute is set to the Columns property. It enables a control to specify how the page parser interprets nested elements within the control's tags when the control is used declaratively on an ASP.NET page. Columns is a property of type BoundColumnsCollection and holds items of the BoundColumn type

[ToolboxData("<{0}:DataIslandGrid runat=server></{0}:DataIslandGrid>")]
[ParseChildren(true,"Columns")]
[PersistChildren(false)]
[Designer(typeof(ReflectionIT.Web.UI.WebControls.Design.DataIslandGridDesigner))]
[DefaultProperty("Columns")]
publicclass DataIslandGrid : System.Web.UI.WebControls.WebControl

The class has a set of public properties which allows you to configure it. The real magic is done in the Render() and OnPreRender() methods:

  • JavaScript code for client-side sorting is added to the Page.
  • The DataTable from the DataSet is rendered to an Xml DataIsland using the WriteXml() method of the DataSet. 
  • An Xml StyleSheet is rendered in a second Xml DataIsland. This StyleSheet is used by the JavaScript to do the sorting. It uses a xsl:for-each loop with a order-by attribute. The value of this attribute is set in the JavaScript.
  • A <table> tag is rendered with a datasrc attribute which is set to the ID of first XmlDataIsland
  • For each Column a table cell (<td>) is rendered within a <thead> section. In this Cell a hyperlink is rendered with a NavigateUrl property to the JavaScript which does the client-side sorting. The Text of the hyperlink is set to the HeaderText property.
  • For each Column a table cell (<td>) is rendered within a <tbody> section. In this Cell a <div> tag is rendered with a datafld attribute which is set to the DataField property.
  • A <tfoot> section is rendered with four hyperlinks for paging: MoveFirst, MovePrevious, MoveNext and MoveLast.
  • All tags are closed.
/// <summary>
/// Add a JavaScript to the Page to sort a column
/// </summary>
/// <param name="e"></param>
override protected void OnPreRender(EventArgs e){

     if(this.Page.Request.Browser.JavaScript == true){
         // Build JavaScript        
         System.Text.StringBuilder s =new System.Text.StringBuilder();
         s.Append("\n<script type='text/javascript' language='JavaScript'>\n");
         s.Append("<!--\n");
         s.Append("function sortColumn(xmldoc, xsldoc, sortcol) {\n");
         s.Append(" xsldoc.selectSingleNode(\"//xsl:for-each\").setAttribute(\"order-by\", sortcol);\n");
         s.Append(" xmldoc.documentElement.transformNodeToObject(xsldoc.documentElement,xmldoc);\n");
         s.Append("}\n");
         s.Append("// -->\n");
         s.Append("</script>\n");

         // Add the Script to the Page
         this.Page.RegisterClientScriptBlock("SortDataIslandGrid", s.ToString());
     }
}

/// <summary>
/// Sends server control content to a provided HtmlTextWriter object, which writes
/// the content to be rendered on the client.
/// </summary>
/// <param name="writer">The HtmlTextWriter object that receives the server control content.</param>
protectedoverridevoid Render(HtmlTextWriter writer) {

     if(_dataSet!=null) {


         // XML
         stringoldNS= DataSet.Namespace;
         DataSet.Namespace ="";

         writer.AddAttribute("id","xml" +this.ClientID);
         writer.RenderBeginTag("XML");

         DataSet.WriteXml(writer, XmlWriteMode.IgnoreSchema);
         writer.RenderEndTag();//XML

         DataSet.Namespace =oldNS ;

         // XSL (sorting)
         if(this.AllowSorting){
             writer.AddAttribute("id","xsl"+this.ClientID);
             writer.RenderBeginTag("XML");

             writer.RenderBeginTag(DataSet.DataSetName);
             writer.AddAttribute("order-by", "?");
             writer.AddAttribute("select", DataTable.TableName);
             writer.AddAttribute("xmlns:xsl", "http://www.w3.org/TR/WD-xsl");
             writer.RenderBeginTag("xsl:for-each");
             writer.WriteBeginTag(DataTable.TableName);
             writer.Write(HtmlTextWriter.TagRightChar);

             foreach(DataColumn colin DataTable.Columns){
                 writer.WriteBeginTag(col.ColumnName);
                 writer.Write(HtmlTextWriter.TagRightChar);
                 writer.WriteBeginTag("xsl:value-of");
                 writer.WriteAttribute("select",col.ColumnName);
                 writer.Write(HtmlTextWriter.SlashChar);
                 writer.Write(HtmlTextWriter.TagRightChar);
                 writer.WriteEndTag(col.ColumnName);
             }

             writer.WriteEndTag(DataTable.TableName);
             writer.RenderEndTag(); //xsl:for-each"
             writer.RenderEndTag();

             writer.RenderEndTag(); //XML
         }
     }

     bool design=(this.Site !=null&&this.Site.DesignMode);
     if(_dataSet!=null| design){
         // Table
         writer.AddAttribute("datasrc","#xml" +this.ClientID);
         writer.AddAttribute("id",this.ClientID);
         writer.AddAttribute("CellPadding",this.CellPadding.ToString());
         writer.AddAttribute("CellSpacing",this.CellSpacing.ToString());
         if(this.AllowPaging){
             writer.AddAttribute("dataPageSize", PageSize.ToString());
         }
         if(!this.BorderWidth.IsEmpty){
             writer.AddAttribute("border", BorderWidth.ToString());
         }
         if(this.CssClass != string.Empty){
             writer.AddAttribute("class", CssClass);
         }

         if(this.ControlStyleCreated &&this.ControlStyle !=null){
             ControlStyle.AddAttributesToRender(writer);
         }
         writer.RenderBeginTag("table");

         // Header
         writer.RenderBeginTag("thead");
         writer.RenderBeginTag("tr");

         foreach(ReflectionIT.Web.UI.WebControls.BoundColumn bcin_columns){
             if(!bc.Width.IsEmpty){
                 writer.AddAttribute("width",bc.Width.ToString());
             }
             writer.RenderBeginTag("th");

             if(this.AllowSorting &bc.Sortable){
                 this.WriteSort(writer,bc.DataField,bc.HeaderText);
             }else{
                 writer.Write(bc.HeaderText);
             }

             writer.RenderEndTag();
         }

         writer.RenderEndTag();// tr
         writer.RenderEndTag();// thead

         // body
         writer.RenderBeginTag("tbody");

         int t =design?(AllowPaging ? PageSize :4) :1;
         for(int x =0; x < t; x++){
             writer.RenderBeginTag("tr");

             foreach(ReflectionIT.Web.UI.WebControls.BoundColumn bcin_columns){
                 bc.Render(writer);
             }
             writer.RenderEndTag(); //tr
         }
         writer.RenderEndTag();// tbody

         // Footer
         if(AllowPaging){
             writer.RenderBeginTag("tfoot");
             writer.RenderBeginTag("tr");
             writer.AddAttribute("colspan", _columns.Count.ToString());
             writer.RenderBeginTag("th");

             this.WritePaging(writer, ".firstPage();","<<");
             this.WritePaging(writer, ".previousPage();","<");
             this.WritePaging(writer, ".nextPage();",">");
             this.WritePaging(writer, ".lastPage();",">>");

             writer.RenderEndTag(); //th
             writer.RenderEndTag();//tr
             writer.RenderEndTag();//tfoot
         }

         writer.RenderEndTag();// table
     }
}

protectedvirtualvoid WritePaging(HtmlTextWriter writer, stringfunction,stringtext){
     writer.AddAttribute("href","javascript:"+this.ClientID +function);
     writer.RenderBeginTag("a");
     writer.Write(HttpUtility.HtmlEncode(text));
     writer.RenderEndTag();//a
     writer.Write(HtmlTextWriter.SpaceChar);
}

protectedvirtualvoid WriteSort(HtmlTextWriter writer, stringdataField,stringheaderText){
     writer.AddAttribute("href","javascript:sortColumn(xml"+this.ClientID +
         ".XMLDocument, xsl"+this.ClientID +".XMLDocument, '+"+dataField+"');");
     writer.RenderBeginTag("a");
     writer.Write(HttpUtility.HtmlEncode(headerText));
     writer.RenderEndTag();//a
     writer.Write(HtmlTextWriter.SpaceChar);
}

You can configure the appearance of the DataGrid easily by assigning a stylesheet classname to the CssClass property of the DataGrid and its BoundColumns. I have also included a DataIslandGridDesigner class which renders the design-time html.

Links:

I have used the following articles to create this control and to write this article:

Conclusion

The Internet Explorer features for Data-Binding to Xml DataIslands are very powerful. The DataIslandGrid control makes it easy to use them in a ASP.NET application. It demonstrates the power of .NET controls.

Any suggestions and feedback for improving this article is most welcome. Send your suggestions and feedback to Fons.Sonnemans@reflectionit.nl

Tags: Web, ASP.NET
12>

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.