Categories
General (9)
General ASP.Net (6)
Javascript (6)
ASP.Net WebForms (6)
GridView Controls (7)
ASP.Net AJAX (2)
ASP.Net MVC (1)
 
 
Archive
Aug 2010 (1)
Jul 2010 (1)
Jun 2010 (1)
May 2010 (1)
Apr 2010 (1)
Mar 2010 (1)
Feb 2010 (2)
Jan 2010 (1)
Dec 2009 (2)
Nov 2009 (5)
Oct 2009 (10)
Sep 2009 (6)
Aug 2009 (2)
 
 
7607 Visits
 
Oct 2009

Difference between ReadOnly and Disabled

What is the difference between ReadOnly="true" and Enabled="false" for a TextBox control?

When a textbox is in ReadOnly mode or is disabled, we cannot get the text of the textbox on page postback. (TextBox1.Text will be empty). However, in the case of ReadOnly mode, the TextBox text is sent as part of Form's postback data. The textbox value can be retrieved using Request.Form["TextBox1"] where TextBox1 is the ClientID of the TextBox. When a textbox is disabled, the TextBox text does not come as part of form postback. So Request.Form["TextBox1"] will be empty.

The above difference is useful in some scenarios. For eg, you have a TextBox with AJAX CalendarExtender. You do not want the user to enter any text in the textbox. So, you can set the TextBox to be ReadOnly. However on postback, you will not get TextBox1.Text set by calendar control. So you can use Request.Form["TextBox1"] to get the selected date. Sample code is shown below:

<asp:TextBox ID="Text1" runat="server" ReadOnly="true" /> <cc:CalendarExtender runat="server" TargetControlID="Text1"> </cc:CalendarExtender>
protected void Page_Load(object sender, EventArgs e) { Response.Write("Form: " + Request.Form["Text1"] + "<br/>"); Response.Write("TB: " + Text1.Text + "<br/>"); }

0 Comment(s), Your comments?

Image with Text for Verification

I want to create an image with text for verification, similar to the ones used in Google, Yahoo in user registration. How can I create this?

The HTML markup for the sample page with image verification will look like something like this:

<form id="form1" runat="server"> <div> <asp:Image ID="VerImage" runat="server" ImageUrl="~/ImageViewer.ashx"/> <asp:TextBox ID="VerText" runat="server" /> <asp:CustomValidator id="VerifyVal" runat="server" ValidateEmptyText="true" ControlToValidate="VerText" OnServerValidate="VerifyVal_ServerValidate">* </asp:CustomValidator> <asp:Button Text="Verify" runat="server" /> </div> </form>
The image is rendered using a ImageViewer.ashx handler. The textbox text is verified using a CustomValidator. In the server-side, we handle the Page load event and CustomValidator ServerValidate event. In the Page load event we create a verification text and store it in a session variable. In the ServerValidate event, we pick the verification text from the Session variable and validate the text in the textbox. The code is as below:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string verText = "Sample"; Session["Verify"] = verText; } } protected void VerifyVal_ServerValidate(object source, ServerValidateEventArgs args) { args.IsValid = false; string verText = (string)Session["Verify"]; if (!String.IsNullOrEmpty(verText)) { if (VerText.Text == verText) { args.IsValid = true; } } }
The image rendering is performed in a handler class - ImageViewer.ashx. The ProcessRequest method gets the verification text from the session variable. This is possible only if the handler class derives from IRequiresSessionState (System.Web.SessionState). IRequiresSessionState is a marker interface. So, no new methods have to be defined.

After getting the verification text, an image object is created from a background image file. Using the graphics object of the image object, we can draw the string. Once the string is drawn, the image object can be streamed into the Response object. The code for the handler is below:

public class ImageViewer : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { Image image = Image.FromFile(context.Server.MapPath("~/red.jpg")); Graphics gp = Graphics.FromImage(image); string text = "Default"; if (context.Session!=null && context.Session["Verify"]!=null) text = (string)context.Session["Verify"]; Font font = new Font(new FontFamily("Arial"), image.Height/3); Brush brush = Brushes.White; PointF point = new PointF(image.Width/4, image.Height/4); gp.DrawString(text, font, brush, point); image.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); } public bool IsReusable { get { return false; } } }

0 Comment(s), Your comments?

Reordering table rows on MouseMove

How can I move the rows of the table by dragging it?

The code below is self-explanatory with comments. It works in IE6

<table id="Grid"> <tr onmousedown="holdRow(this);" style="position: relative;"> <td width="400"> Name 1 </td> <td width="400"> Test </td> </tr> <tr onmousedown="holdRow(this);" style="position: relative;"> <td> Name 2 </td> <td width="400"> Test </td> </tr> <tr onmousedown="holdRow(this);" style="position: relative;"> <td> Name 3 </td> <td width="400"> Test </td> </tr> <tr onmousedown="holdRow(this);" style="position: relative;"> <td> Name 4 </td> <td width="400"> Test </td> </tr> </table>
The javascript for the above table is below:
<script type="text/javascript"> var selRow = null; var selRowTop = 0; var selIndex = 0; var clientY = 0; var bgColor = ""; var grid; function move() { if (selRow) { // Change the bgColor of row to gray selRow.bgColor = "Gray"; // Move the row selRow.style.pixelTop = window.event.clientY - clientY; var top = selRowTop + selRow.style.pixelTop; // If the row is moved beyond table boundary, reset the row if (top > grid.offsetHeight) { selRow.style.pixelTop = 0; releaseRow(); } if (top < 0) { selRow.style.pixelTop = 0; releaseRow(); } } } function holdRow(row) { selRow = row; grid = document.getElementById("Grid"); // Get the position of the selected row within the table for (var i = 0; i < grid.rows.length; i++) { if (grid.rows[i] == selRow) { break; } selRowTop += grid.rows[i].offsetHeight; } // Get the row index and store it in selIndex selIndex = i; bgColor = selRow.bgColor; // Store the initial position of the row in the screen clientY = window.event.clientY; // For moving the row, handle the onmousemove event of document document.onmousemove = move; document.onmouseup = releaseRow; } function releaseRow() { if (selRow) { // If the row is moved, adjust the position if(selRow.style.pixelTop!=0) { adjustGrid(); } // Reset styling, variables and event handler selRow.bgColor = bgColor; bgColor = ""; selRow = null; selRowTop = 0; selIndex = 0; document.onmousemove = null; document.onmouseup = null; } } function adjustGrid() { // Based on position, rearrange the table var pos = selRowTop + selRow.style.pixelTop; if (selRow.style.pixelTop > 0) { pos += selRow.offsetHeight; } var top = 0; var i = 0; // Get the new position of the row within the table for (i = 0; i < grid.rows.length; i++) { if (pos >= top && pos < (top + grid.rows[i].offsetHeight)) { break; } top += grid.rows[i].offsetHeight; } if (selRow.style.pixelTop > 0) { i = i + 1; } // Reset the relative Top to zero but rearrange table selRow.style.pixelTop = 0; // Insert in the appropriate position // Else append to the end of the table // IE automatically removes the node from table and inserts! var ins = grid.childNodes[0].childNodes[selIndex]; if (i < grid.rows.length) { var ref = grid.childNodes[0].childNodes[i]; grid.childNodes[0].insertBefore(ins, ref); } else if (i = grid.rows.length) { grid.childNodes[0].appendChild(ins); } } </script>

1 Comment(s), Your comments?

GridView as email attachment

How do I send the contents of a GridView as an email attachment?

GridView can be rendered into a string using the RenderControl() method. From the string, a buffer (of bytes) can be extracted assuming ASCII encoding. This buffer can be used as email attachment by streaming it through a MemoryStream object. The code is below:

protected void Submit_Click(object sender, EventArgs e) { // Render the contents of the GridView into a string StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); HtmlTextWriter htw = new HtmlTextWriter(sw); GridView1.RenderControl(htw); // Get the byte buffer from the string byte[] buffer = new byte[sb.Length]; ASCIIEncoding enc = new ASCIIEncoding(); buffer = enc.GetBytes(sb.ToString()); // Create attachment from MemoryStream MemoryStream ms = new MemoryStream(buffer); Attachment att = new Attachment(ms, "GridReport.xls"); }

0 Comment(s), Your comments?

Image Handler

I have images stored in a network drive in another server. How can I show the image in a web page?

If for some reason, it is not possible to create a virtual directory within IIS, then creating a handler for streaming images is the best solution. A handler is a class derived from IHttpHandler. It has a method called ProcessRequest which contains the Request and Response objects. The code for showing streaming images in a webpage using handler is as follows:

public class ImageViewer : IHttpHandler { public void ProcessRequest(HttpContext context) { string id = context.Request.QueryString["Id"]; if (!String.IsNullOrEmpty(id)) { // Retrieve the image filename based on id // For our example, the image filename is C:\red.jpg string filePath = "C:\\red.jpg"; // The above path could be any network drive FileStream fs = new FileStream(filePath, FileMode.Open); byte [] bytes = new byte[fs.Length]; fs.Read(bytes, 0, (int)fs.Length); context.Response.BinaryWrite(bytes); } } public bool IsReusable { get { return false; } } }
In the above code, a filestream object is used to access the file in a network drive. The image is read into a binary buffer (byte []) and is written into the Response object.

In the ASPX page, you will write code like below to access the image using Handler (.ashx):

<img src="ImageViewer.ashx?id=1" />

3 Comment(s), Your comments?

Nested GridViews

I have a nested GridView in my project. The top level grid will display a list of names and a link-button. On clicking the link-button, the detail (child) grid will be shown with a OK button. When the OK button is pressed, the child grid should disappear

I will use the Pubs database, Authors table. The top-level grid called AuthorGrid will display last-names. The child-grid will display first-name for the selected author

Below is the HTML markup:

<asp:GridView ID="AuthorGrid" runat="server" DataSourceID="AuthorSql" AutoGenerateColumns="false" DataKeyNames="au_lname" OnSelectedIndexChanged="AuthorGrid_SelectedIndexChanged"> <Columns> <asp:BoundField HeaderText="Author" DataField="au_lname" /> <asp:TemplateField> <ItemTemplate> <asp:GridView ID="DetailGrid" runat="server" OnRowCommand="DetailGrid_OK" AutoGenerateColumns="false"> <Columns> <asp:BoundField HeaderText="First name" DataField="au_fname" /> <asp:ButtonField CommandName="OK" Text="OK" /> </Columns> </asp:GridView> </ItemTemplate> </asp:TemplateField> <asp:CommandField ShowSelectButton="true" SelectText="Show" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="AuthorSql" runat="server" ConnectionString = "<%$ ConnectionStrings:Pubs %>" SelectCommand="SELECT au_lname FROM Authors" ></asp:SqlDataSource> <asp:SqlDataSource ID="DetailSql" runat="server" DataSourceMode="DataSet" ConnectionString = "<%$ ConnectionStrings:Pubs %>" SelectCommand="SELECT au_fname FROM Authors WHERE au_lname=@lname" > <SelectParameters> <asp:Parameter Type="String" Name="lname" /> </SelectParameters> </asp:SqlDataSource>
Note that AuthorGrid is bound to AuthorSql and DetailGrid is not bound. DetailGrid will bind to DetailSql (SqlDataSource) when an author is selected in the AuthorGrid. The code for showing DetailGrid is found in the OnSelectedIndexChanged EventHandler of the AuthorGrid:
protected void AuthorGrid_SelectedIndexChanged(object sender, EventArgs e) { string lname = (string)AuthorGrid.SelectedValue; DetailSql.SelectParameters["lname"].DefaultValue = lname; DataSourceSelectArguments dssa = new DataSourceSelectArguments(); DataView ds = (DataView)DetailSql.Select(dssa); GridView DetailGrid = (GridView)AuthorGrid.SelectedRow .FindControl("DetailGrid"); DetailGrid.DataSource = ds; DetailGrid.DataBind(); }
Finally, when the OK button of the DetailGrid is clicked, the DetailGrid should disappear. This can be done by binding the DetailGrid to an empty datasource as follows:
protected void DetailGrid_OK(object sender, GridViewCommandEventArgs e) { if (e.CommandName == "OK") { GridView DetailGrid = (GridView)e.CommandSource; DetailGrid.DataBind(); } }

0 Comment(s), Your comments?

Referer in Request Header

I have a page which I do not want to the user to access directly by typing the hyperlink. If the user directly accesses the page, I want to display a 500 Internal Server Error

The Request header has a key called Referer. This key contains the URL from which the user has come to the page. If the user clicked on a link in Page1 and came to Page2, the Referer header in Page2 will contain the URL of Page 1. Here is some code:

string referer = Request.Headers["Referer"]; if (String.IsNullOrEmpty(referer)) { Response.Clear(); Response.Status = "500 Internal Server Error"; Response.StatusCode = 500; Response.End(); }

1 Comment(s), Your comments?

RadioButtonList OnClick

I have a RadioButtonList. When the user selects the first RadioButton in the list, I want a textbox to be displayed. For all other RadioButtons, I want this textbox to be hidden. I want this behaviour to be consistent when the user presses the Back button after navigating out of the page

RadioButtonList is a table of RadioButtons having the same name. Each RadioButton has a OnClick event that we can handle in Javascript. Here is the code for hiding/unhiding the textbox on Radiobutton click

<asp:RadioButtonList ID="lstRadio" runat="server"> <asp:ListItem Text="Indv" Value="0" OnClick="toggle();"></asp:ListItem> <asp:ListItem Text="Entity" Value="1" OnClick="toggle();"></asp:ListItem> </asp:RadioButtonList> <asp:TextBox ID="txtDOB" runat="server"></asp:TextBox>
Note the OnClick on ListItem. The OnClick is a client-side event handler. The toggle() function is below:
function toggle() { var lst = document.getElementsByName('lstRadio'); if (lst[1].checked == true) document.getElementById('txtDOB').style.display = 'inline'; else document.getElementById('txtDOB').style.display = 'none'; }
The Radio buttons with name - lstRadio can be got by document.getElementsByName(). The first radiobutton is the second element in the array or lst[1]. This is because the RadioButtonList server control renders the table holding the radiobuttons with the same name - lstRadio. Finally, to ensure that this behaviour is consistent across postbacks and back-button navigation, the body onload event handler should call the toggle() function. This ensures that the behaviour of the RadioButtonList is consistent.
<body onload="toggle();">

1 Comment(s), Your comments?

ValidatorEnable Javascript function

I have a dropdownlist with different options like Name, Phone, Date etc. There is a textbox in which I enter values for these options. Each of these options have validator controls associated with it. On selecting the dropdown, only the validators specific to the selected value should fire

Here is the ASPX markup that contains the dropdownlist, textbox and validators

<form id="form1" runat="server"> <div> <asp:DropDownList ID="TypeList" runat="server" OnChange="TypeList_Change(this);"> <asp:ListItem Value="Name" Selected="True">Name</asp:ListItem> <asp:ListItem Value="Date">Date</asp:ListItem> <asp:ListItem Value="Phone">Phone</asp:ListItem> </asp:DropDownList> </div> <asp:TextBox ID="ValueText" runat="server"></asp:TextBox> <asp:RequiredFieldValidator ID="NameReq" runat="server" ControlToValidate="ValueText">*</asp:RequiredFieldValidator> <asp:RequiredFieldValidator ID="DateReq" runat="server" ControlToValidate="ValueText">*</asp:RequiredFieldValidator> <asp:CompareValidator ID="DateVal" runat="server" ControlToValidate="ValueText" Type="Date" Operator="DataTypeCheck">*</asp:CompareValidator> <asp:CompareValidator ID="PhoneVal" runat="server" ControlToValidate="ValueText" Type="Integer" Operator="DataTypeCheck">*</asp:CompareValidator> <asp:Button ID="SubmitBtn" runat="server" Text="Submit"/> </form>

To enable or disable a validator, the javascript ValidatorEnable(val, enable) can be used. The way to find the list of validators for a particular selection is to hard-code the validator IDs in a 2D array. The javascript function for OnChange event handler of the dropdownlist is given below:

<script type="text/javascript" > var list = [['NameReq'], ['DateReq', 'DateVal'], ['PhoneVal']]; function TypeList_Change(c) { for (var i = 0; i < list.length; i++) { var valList = list[i]; var enabled = (i == c.selectedIndex); for (var j = 0; j < valList.length; j++) { var validator = document.getElementById(valList[j]); ValidatorEnable(validator, enabled); } } } </script>
When the document is loaded initially or on any postback, the validators have to be enabled appropriately. So add this code to the body onload eventhandler
<body onload="TypeList_Change(document.getElementById('TypeList'));">

0 Comment(s), Your comments?

WebMethod Example

I want a label box to be refreshed every one second with a random number generated at the server

This is a classic example of WebMethods. WebMethods are written on the server side in the page class. WebMethods are static. Here is a simple implementation of a webmethod:

private static Random random = new Random(1000); [WebMethod] public static int GetRandomNumber() { return random.Next(10, 99); }

To be able to call this WebMethod from Javascript, the asp:ScriptManager should have the EnablePageMethods property set to true:

<form id="form1" runat="server"> <asp:ScriptManager runat="server" EnablePageMethods="true"></asp:ScriptManager> <asp:Label ID="Random" runat="server"></asp:Label> </form>

From Javascript, the WebMethod can be called using the syntax PageMethods.FunctionName(Arg0, Arg1, OnSucceededCallBack); WebMethods are executed asynchronously. So a callback function has to be provided. Here is an example of updating a label box with the random number

<script type="text/javascript" > setTimeout("PageMethods.GetRandomNumber(setRandom);", 1000); function setRandom(result) { document.getElementById("Random").innerText = result; setTimeout("PageMethods.GetRandomNumber(setRandom);", 1000); } </script>

0 Comment(s), Your comments?