Tuesday, November 16, 2010

Add JavaScript Dynamically to ASP.NET UpdatePanel

Use the following example:

System.Text.StringBuilder sb = new System.Text.StringBuilder();      
sb.Append(@" var inputs = document.getElementsByTagName('input');                                  for (var i = 0; i < inputs.length; i++) {
         if (inputs[i].type == 'text') {                
            inputs[i].onkeypress = function (event) {
               event = event || window.event;

               return myJavaScriptFunction(event);}
           }}"
       );
ScriptManager.RegisterClientScriptBlock (this, this.GetType(), "ajax", sb.ToString(), true); 

What it does is attaches  a JavaScript function (defined elsewhere) to each input box on the page on the key press event, and then registers it for use with a control that is inside an UpdatePanel.  This could be used for user input validation. The code has been verified in IE and Firefox.

Wednesday, November 10, 2010

ASP.NET GridView Subclass with Dynamic Footer Totals

A frequent requirement when using an ASP.NET GridView on a web page is to have a footer with totals for numeric columns in the GridView. Here is a GridView subclass that calculates footer totals dynamically.  It requires 3 parameters:

FirstComputedColumnIndex - the for index of the first column in the data set to be computed
FirstVisbleComputedColumnIndex - for the index of the first computed column to be shown
NumberOfComputedColumns - for the number of computed columns.

Here is the class code:

namespace Eric.TotalGrid {
  public partial class GridView : System.Web.UI.WebControls.GridView
    {
        private Indexer footerTotals;
        public int FirstComputedColumnIndex { get; set; }
        public int FirstVisbleComputedColumnIndex { get; set; }
        public int NumberOfComputedColumns { get; set; }    

        protected override void OnLoad(EventArgs e)
        {
            ShowFooter = true;
            base.OnLoad(e);
        }
        protected override void OnInit(EventArgs e)
        {
            footerTotals = new Indexer(NumberOfComputedColumns);
            InitializeComponent();
            base.OnInit(e);
        }

        private void InitializeComponent()
        {
            this.RowDataBound += new GridViewRowEventHandler(this.GridView1_RowDataBound);
        }

        protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {           

            DataRowView tableData = e.Row.DataItem as DataRowView;

            if (e.Row.RowType == DataControlRowType.DataRow)
            {            
                for (int i = FirstComputedColumnIndex; i < (FirstComputedColumnIndex + NumberOfComputedColumns); i++)
                {               
                    if (tableData[i] != DBNull.Value)
                    {
                        decimal result = 0;
                        if (Decimal.TryParse(tableData[i].ToString(), out result))
                        {
                            footerTotals[i - FirstComputedColumnIndex] += result;
                        }
                    }
                }
            }
            else if (e.Row.RowType == DataControlRowType.Footer)
            {
                for (int i = 0; i < NumberOfComputedColumns; i++)
                {
                    if (e.Row.Cells.Count > (i + FirstVisbleComputedColumnIndex))
                        e.Row.Cells[i + FirstVisbleComputedColumnIndex].Text = footerTotals[i].ToString();
                }
            }
        }
}



The key to this GridView is using an Indexer class that can be accessed like an array. Here is its listing:


class Indexer
        {
            private int _upperLimit;      

            private decimal[] myArray;

            public Indexer(int limit)
            {
                _upperLimit = limit;
                myArray = new decimal[_upperLimit];
            }
            public decimal this[int index]   // Indexer declaration
            {
                get
                {
                    // Check the index limits.
                    if (index < 0 || index >= _upperLimit)
                        return 0;
                    else
                        return myArray[index];
                }
                set
                {
                    if (!(index < 0 || index >= _upperLimit))
                        myArray[index] = value;
                }
            }
        }
The Indexer class can be nested within the GridView subclass.


The last example shows how to use the custom GridView on a ASP.NET web page:
First,  use the register tag:
<%@ Register Namespace="Eric.TotalGrid" TagPrefix="x" Assembly="TotalGrid" %>

Then, use it just like any other GridView:

<x:GridView runat="server" ....
FirstComputedColumnIndex="4" FirstVisbleComputedColumnIndex="3" NumberOfComputedColumns="10"  >