ASP.Net
    Release Manager    One click builds from Subversion.    Select which issue items to build.

How to Work With a GridView Row in JavaScript

by JBrooks 14. July 2009 16:40

The question came up asking how to change something in a GridView row based on something else in that row without doing a postback.   So I created a simple example where if you check a CheckBox then another column in that row would have it's background color changed.  I did this in a generic way by sending the checkbox to the function by using the keywork "this" and then getting a reference to the row.  Here is what it looks like:

So when you check the CheckBox for a given row, it's "Name" column's background changes color to Aqua.

Here is the code behind to bind the table:

using System;
using System.Data;

namespace BlogTests
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    
        if (!IsPostBack)
            {
               DataTable dt = new DataTable();

                dt.Columns.Add("Include", typeof(Boolean));
                dt.Columns.Add("Name", typeof(String));
                dt.Rows.Add(new Object[] { 0, "Jim" });
                dt.Rows.Add(new Object[] { 0, "Jen" });
                dt.Rows.Add(new Object[] { 0, "Kylie" });
                GridView1.DataSource = dt;
                GridView1.DataBind();
            }
        }

    }
}

 

and then the .aspx page:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="BlogTests._Default" %>

<!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 runat="server">
    <title>Row Test</title>
    <style type="text/css">
        .selected
        {
            background-color: Aqua;
            font-weight: bold;
        }
    </style>
</head>
<body>

    <script type="text/javascript">
        function toggleSelected(sender) {
            var row = GetParentElementByTagName(sender, "TR");

            if (sender.checked)
                row.cells[1].className = "selected";
            else
                row.cells[1].className = '';

        }


        function GetParentElementByTagName(element, tagName) {
            var element = element;
            while (element.tagName != tagName)
                element = element.parentNode;
            return element;
        }
    </script>

    <form id="form1" runat="server">
    <div>
    </div>
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
        <Columns>
            <asp:TemplateField HeaderText="Include" SortExpression="Include">
                <ItemTemplate>
                    <asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Bind("Include") %>' onclick="toggleSelected(this)" />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name">
                <ItemStyle HorizontalAlign="Left" />
            </asp:BoundField>
        </Columns>
    </asp:GridView>
    </form>
</body>
</html>

 

Tags:

ASP.Net | Development | GridView

Attaching upload files to a record.

by JBrooks 2. July 2009 11:31

One of our applications has a page for our users to report bugs.  We wanted to allow them to “attach” one or more files to the bug record.  The files could be screen shots, spreadsheets, etc.    So the bug entry page would have the normal data entry part and have the following box at the bottom of the page:

 

If you click the FileName it will download the file if IIS is setup to send that extention.  All this should be made into a user control or a server control, but for now I have the code in the page.  Here are the key parts:

// the page has a property that returns the bug's record id.

private int id

{ get { return Convert.ToInt32(Request.QueryString["id"]); } }

 

 

private string uploadDir

{ get { return System.AppDomain.CurrentDomain.BaseDirectory+ "\\Uploads\\"; } }

 

protected void btnUpload_Click(object sender, EventArgs e)

   if (this.FileUpload1.HasFile)

   {  //we rename the file to start with the id and an underscore.

   string fileName = uploadDir + id.ToString() + "_" + FileUpload1.FileName;

 

   FileUpload1.SaveAs(fileName);

 

   bindFiles();

   } else { setErrorMessage("You have not specified a file."); }

 }

 

protected void bindFiles()

{

// make a table to hold the file's information.

    DataTable dt = new DataTable();

    dt.Columns.Add("FileName", typeof(String));

    dt.Columns.Add("Created", typeof(DateTime));

    dt.Columns.Add("Size", typeof(Int32));

    dt.Columns.Add("id", typeof(Int32));

 

         // get a list of files that start with our id.

    string[] files = Directory.GetFiles(uploadDir,id.ToString()+"_*.*");

 

//populate the table.

    foreach (string fileName in files)

    {

        DataRow dr = dt.NewRow();

        FileInfo fi = new FileInfo(fileName);

        // at this point we need to strip off the id.

        dr["FileName"] = fileName.Substring(fileName.LastIndexOf("\\") + 2 + id.ToString().Length);

        dr["Created"] = fi.CreationTime;

        dr["Size"] = fi.Length;

        dr["id"] = this.id;

 

        dt.Rows.Add(dr);

    }

 

// now bind the table to our gridview

    this.gvFiles.DataSource = dt;

    this.gvFiles.DataBind();

 

}

 

protected void lbDelete_Click(object sender, EventArgs e)

{

         //Don't like how fragile this is, but good enough for now.

    string fileName = uploadDir + id.ToString() + "_" + ((HyperLink)((GridViewRow)((LinkButton)sender).Parent.Parent).Cells[1].Controls[0]).Text;

 

    File.Delete(fileName);

 

    bindFiles();

}

 

 

 Here is the related mark-up from the aspx page:

<div  id="divFiles" style="border: solid 1px black">

<span id="Span1" style="font-size:X-Large;font-weight:bold;">FILES</span>

<br />

    <asp:FileUpload ID="FileUpload1" runat="server" />&nbsp;&nbsp;&nbsp;

    <asp:Button ID="btnUpload" runat="server" Text="Upload" OnClick="btnUpload_Click" /><br />

    <br />

    <asp:GridView ID="gvFiles" runat="server" AutoGenerateColumns="False" Caption="<strong>FILES</strong>"

        CaptionAlign="Top" CellPadding="4" ForeColor="#333333" GridLines="None">

        <RowStyle BackColor="#FFFBD6" ForeColor="#333333" />

        <Columns>

            <asp:TemplateField InsertVisible="False" ShowHeader="False">

                <ItemTemplate>

                    <asp:LinkButton ID="lbDelete" runat="server" CausesValidation="False" CommandName="Delete"

                        Text="Delete" OnClientClick="confirm('Are you sure you want to delete this file?');" OnClick="lbDelete_Click"></asp:LinkButton>

                </ItemTemplate>

            </asp:TemplateField>

            <asp:HyperLinkField DataTextField="FileName" SortExpression="FileName" Text="FileName"

                HeaderText="FileName" DataNavigateUrlFormatString="~/Uploads/{0}_{1}"

                DataNavigateUrlFields="id,FileName" >

                <ItemStyle HorizontalAlign="Left" />

            </asp:HyperLinkField>

            <asp:BoundField DataField="Created" DataFormatString="{0:M/d/yy H:mm}" HeaderText="Created"

                SortExpression="Created"  />

            <asp:BoundField DataField="Size" HeaderText="Size" SortExpression="Size" DataFormatString="{0:#,###,###}" >

                <ItemStyle HorizontalAlign="Right" />

            </asp:BoundField>

        </Columns>

        <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />

        <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />

        <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />

        <AlternatingRowStyle BackColor="White" />

    </asp:GridView>

</div>

<br />

 

 

Tags:

ASP.Net | GridView | Development

Formatting Dates

by JBrooks 2. July 2009 09:37

I was having a lot of code that looked like the following:

         if(dr["StartTime"] != DBNull.Value)   
                tbStartTime.Text = dr["StartTime"].ToString("M/d/yy H:mm");
         else

              tbStartTime.Text = "";

and:

         tbStartTime.Text = DateTime.Now.ToString("M/d/yy H:mm");

 

You usually use the same formatting throughout an application so I simplified this by using the following function:

        public string formatDate(object date)
        {
            if (date != DBNull.Value)
                return Convert.ToDateTime(date.ToString()).ToString("M/d/yy H:mm");
            else
                return "";
        }

 So now I can have my formatting in one place and use this like so:

       tbStartTime.Text = formatDate(dr["StartTime"]);

 and using the same function:

     tbStartTime.Text = formatDate(DateTime.Now);

 

 

 

 

Tags:

ASP.Net | Development

Log only the start and end of an outage condition

by JBrooks 22. April 2009 06:25

We have an asp.net page that auto refreshes every 8 seconds using   <meta http-equiv="refresh" content="8">

This page would pull data from a linked server and whenever that link or the target server were down it would fill up our error log with an entry every 8 seconds until it came back up.   This is not very useful, so we wanted an entry for when the exceptions started and then one more entry for when it cleared.   And I wanted a way of matching off each set of start / stop events. 

This is how I did it.  First I added the following property to my page:

private bool inErrorState

{ get { return Request.Cookies["myPageError"] != null; }

set

{

    if (value != inErrorState)

    {

        if (value)  // first error.

        {

            string errorGuid = Guid.NewGuid().ToString();

            cApp.db.LogException("myPageError start of error, ErrorGuid: " + errorGuid);

            Response.Cookies["myPageError"].Value = errorGuid;

            Response.Cookies["myPageError"].Expires = DateTime.Now.AddDays(100);

 

        }

        else // coming out of error.

        {

            if (Request.Cookies["myPageError"] != null)

            {

                cApp.db.LogException("myPageError end of error, ErrorGuid: " + Request.Cookies["myPageError"].Value);

                Response.Cookies.Set(Request.Cookies["myPageError"]);

                Response.Cookies["myPageError"].Expires = DateTime.Now.AddDays(-1);

            }

 

 

        }

    }

}

}

 

So when the error first occurs the errorGuid is created, logged and then saved in the cookie. When it comes out of the error condition the errorGuid is again logged, but with different text, and then the cookie is cleared.

To use this property I just needed to set it to false if the databinding was sucessful and to true in the catch block when an exception is thrown.  Like such:

  try

            {

                myGrid.DataBind();

                inErrorState = false;

             }

            catch (Exception ex)

            {

              …

              inErrorState = true;

             }

This is all it took to just capture the start of an error condition and the matching clear of that condition.

 

 

 

 

 

 

 

Tags:

ASP.Net

Where to put the connection string

by JBrooks 24. February 2009 08:10
Machine.config is used for machine specific items - thus the name. It never get moved from machine to machine.  So that is where you put your connection strings.  Doing this you will never have the horror of realizing your QA team has been hammering against your production data because someone forgot to account for the web.config when it was moved DOWN from prod to back out a bad release to QA (or whatever).  And all your web.configs will be the same and easy to promote when they do change.

You can also add a value to the machine.config so that you can tell which environment you are in at runtime.

So in my machine.config I added:
  <appSettings>
    <add key="ADEDevelopmentEnvironment" value="Yes"/>
  </appSettings>

Then in my code I have:
If Not String.IsNullOrEmpty(ConfigurationManager.AppSettings("ADEDevelopmentEnvironment")) Then
            Me.Label1.Text = "You are STILL in Dev?!!!"
Else
            Me.Label1.Text = "You are on production"
End If

Tags:

ASP.Net | Development

GridView Sort Column Arrow Performance

by JBrooks 23. February 2009 16:11

I see code like the following a lot:

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.Header)
            if (String.Empty != this.GridView1.SortExpression)  
                     AddSortImage(e.Row);             
           
}

The problem with this is that it fires for each row in the GridView slowing performance.  A better way is the following which only fires once per GridView binding:

protected void GridView1_DataBound(object sender, EventArgs e)
{
     if
(String.Empty != this.GridView1.SortExpression) 
            AddSortImage(GridView1.HeaderRow);
}

The supporting methods are:

void AddSortImage(GridViewRow headerRow) 

     int
iCol = GetSortColumnIndex();
     if
(-1 == iCol) 
           return

     // Create the sorting image based on the sort direction.

     Image sortImage = new Image();
     if
(SortDirection.Ascending == this.GridView1.SortDirection) 

{             sortImage.ImageUrl = @"~\Images\BlackDownArrow.gif";
               sortImage.AlternateText = "Ascending Order";
}
     else 

{
             sortImage.ImageUrl = @"~\Images\BlackUpArrow.gif";

             sortImage.AlternateText = "Descending Order";

}
      // Add the image to the appropriate header cell.
        headerRow.Cells[iCol].Controls.Add(new LiteralControl("&nbsp;"));
        headerRow.Cells[iCol].Controls.Add(sortImage);
}

public int GetSortColumnIndex()
{
      // Iterate through the Columns collection to determine the index
      // of the column being sorted. 
      foreach (DataControlField field in GridView1.Columns)
       {
             if (field.SortExpression == this.GridView1.SortExpression)
               {
                  return this.GridView1.Columns.IndexOf(field);
                }
         }
      return -1;
}

Tags:

ASP.Net | GridView

Connection Pool Misconceptions

by JBrooks 12. February 2009 08:38
Below is the sql to show how many connection are being used from my application.

declare @Database varchar(30),
    @LoginName varchar(30)

set @Database = 'MyDB'
set @LoginName = 'MyLoginName'

select max(blocked) hasBlocking,
    count(1) [Count],
    sum(open_tran) open_trans,
    max(waittime) maxWaitTime
from master.dbo.sysprocesses (nolock)
where db_name(dbid) = @Database and convert(sysname, rtrim(loginame)) = @LoginName
        
We needed this because there was a problem where our application would use up 100 connections (the default) and then bomb out.  The root cause was because of 2 misconceptions that a developer had.

First misconception:
Calling Close() on a DataReader closed the Connection.  This only releases the Connection object from the DataReader, but this does not close it.  You need to call Close() on the Connection object.  You can test this by seeing the Connection object's State will still be "Open" after calling Close()on the DataReader.

Second misconception:
Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. For more information. For more information on this, see:
http://msdn2.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.close(VS.85).aspx

So if these 2 misconceptions are cleared up in your mind you are a lot less likely to run into this connection pool problem.

 

Tags:

ASP.Net | Development

Checking All CheckBoxes in a GridView Using Client-Side Script

by JBrooks 11. February 2009 11:48

Given a GridView like the one below, I want to add the ability to check the check box in the header and have that event check all of the checkboxes in each row.

 

I did this by adding 12 lines of JavaScript code and adding 1 attribute to my header template.   Below is the markup followed by the code-behind. The parts I added to this simple page are in bold.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Test check all CheckBoxes</title>
       <script type="text/javascript" language="javascript">
        function changeAllCheckBoxes(sender) {
            var gridViewRows = GetParentElementByTagName(sender, "TABLE").rows;
            for (var i = 1; i < gridViewRows.length; ++i) {
                gridViewRows[i].cells[0].childNodes[0].checked = sender.checked;
            }
        }

        function GetParentElementByTagName(element, tagName) {
            var element = element;
            while (element.tagName != tagName)
                element = element.parentNode;
            return element;
        }

    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
    </div>
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
        Caption="Pick Some Technologies" BackColor="White" BorderColor="#CC9966"
        BorderStyle="None" BorderWidth="1px" CellPadding="4">
    <Columns>
            <asp:TemplateField HeaderText="Include" SortExpression="Include">
                <HeaderTemplate>
                    <asp:CheckBox ID="CheckBox1" runat="server" onclick="changeAllCheckBoxes(this)" />
                </HeaderTemplate>
                <ItemTemplate>
                    <asp:CheckBox ID="CheckBox1" runat="server"  />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
            <asp:BoundField DataField="Name" HeaderText="Technology" />
        </Columns>
        <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="#FFFFCC" />
    </asp:GridView>
    </form>
</body>
</html>

using System;
using System.Data;

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DataTable dt = new DataTable();

            dt.Columns.Add("Include", typeof(Boolean));
            dt.Columns.Add("Name", typeof(String));
            dt.Rows.Add(new Object[] { false, "C#" });
            dt.Rows.Add(new Object[] { false, "ASP.Net" });
            dt.Rows.Add(new Object[] { false, "SQL Server" });
            dt.Rows.Add(new Object[] { false, "VB.Net" });

            GridView1.DataSource = dt;
            GridView1.DataBind();

        }
    }
}
 

 

 

Tags:

ASP.Net | Development | GridView