Pranay Rana: January 2012

Monday, January 23, 2012

Bug in Gridview Editing

Post is about the bug I found when we do inline editing in GridView control of ASP.Net in web application.

To understand this fully follwing is my gridview code in AspX file

        
        
        
        
            
                
                    
                
                
                    
                    
                    
                
            
        
        
            
        
    
As you see in code I have attahced RowDataBound which fires when data get bound with the each row of the grid and RowEditing which get fire when user press edit button of the row in gridview.

Code in .Aspx.cs File
#region Grid Events
    protected void grdView_RowEditing(object sender, GridViewEditEventArgs e)
    {
        grdFXRate.EditIndex = e.NewEditIndex;
        BindGrid();
    }

    protected void grdView_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        grdView.EditIndex = -1;
        BindGrid();
    }

    protected void grdView_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        //get data and update
        int Currency_Rate = 0;
        TextBox txtRate = row.FindControl("txtRate") as TextBox;
        if (txtRate != null)
            Currency_Rate = Convert.ToDouble(txtRate.Text);

        saveDetails();
        grdView.EditIndex = -1;
        BindGrid();
    }

    protected void grdView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowState == DataControlRowState.Edit )
        {
            GridViewRow row = e.Row;
            TextBox txtRate = row.FindControl("txtRate") as TextBox;
            if (txtRate != null)
                txtRate.Attributes.Add("onKeypress", "IntegerAndDecimal(event,'" + txtRate.ClientID + "',true)");
        }
    }
    #endregion Grid Events

As you see in code I have written code RowDataBound which find textbox control and attach javascript with it.  And second thing to notedown is that it finds textbox and attach script with it when row is in edit mode. This code works fine its attach script wwith the textbox when row is in edit mode.
Problem
But this code dont work when I click on edit butoon of alternet row which means that it not satisfy if condition. In Edit mode alternet row sate is "Alternet | Edit" where as when you click edit of non-alternetrow rostate is "Edit" which statify the if condition.

You weill get edit by below image where in immediate window it shows sate of alternet row.

Solution
Following is solution to avoid problem with the alternet row edit.
protected void grdView_RowDataBound(object sender, GridViewRowEventArgs e)
{
     if ((e.Row.RowState & DataControlRowState.Edit) > 0)
     {
          GridViewRow row = e.Row;
          TextBox txtRate = row.FindControl("txtRate") as TextBox;
          if (txtRate != null)
               txtRate.Attributes.Add(
                    "onKeypress", "IntegerAndDecimal(event,'" + txtRate.ClientID + "',true)");
     }
}
As you see in code condtion e.Row.RowState & DataControlRowState.Edit satisfy the for both alternet and non-alternet row and works fine.

Wednesday, January 18, 2012

Exposing Custom event from custom control

In this post I m going to discuss about registering custom event in custom control. Recently In my project I have created user control it’s consist of one label control and dropdown box. This user control is common control which can be used in whole project to avoid writing repeated code for binding and also validation code for the same.

Ascx file i.e user control file
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CommonDropDownControl.ascx.cs"
    Inherits="ValidDropDown" %>
<div>
<span id="spnRequired" runat="server"><b class="contentframework-required-asterisk">*</b></span>
    <asp:label id="lblText" runat="server" wrap="false"></asp:label>
     <asp:dropdownlist id="ddlDropDown" onselectedindexchanged="ddlDropDown_SelectedIndexChanged" runat="server" width="137px">
                    </asp:dropdownlist>
     <asp:requiredfieldvalidator controltovalidate="ddlDropDown" enableclientscript="False" errormessage="Selection Invalid!" forecolor="#FF0000" id="valList" initialvalue="0" runat="server">
 
</asp:requiredfieldvalidator></div> 

Now as you can see in above code I have attached as requirefieldvalidator to validate the control which get fire when no value is selected by user.
But the important thing to note here is I have written SelectedChange event with the dropdown control which I want to expose, so that I can write different code on each page where it utilize. Because the problem with the usercontrol is when I attached event with the any control that is part of usercontrol event get encapsulated in the code of that usercontrol and that's why we cannot able to write different code on each page where it is utilize and require to expose.
So in following code I will show how you can expose the change event and how you can utilize it on your page when using usercontrol.


Step 1 : Register event
public event EventHandler DrpChange;

as you see in above code I have registered event of delegate type EventHandler and name of it is DrpChange. On the page I need to register DrpChange which get fire when user do change the selection in the dropdown box of the usercontrol. How I do this will so later on in this post.


Step 2 : Virtual function to handle raised event
public virtual void OnDropDownChange()
    {
        if (DrpChange != null)
        {
            this.DrpChange(this, EventArgs.Empty);
        }
    }
above code there is virtual function which handle the event raise from the page by the control. This function is responsible for calling the code written on page i.e event code written on the page.


Step 3 : Register on Change Event of dropdown in ASCX.CS file
protected void ddlDropDown_SelectedIndexChanged(object sender, EventArgs e)
    {
        this.OnDropDownChange();
    }

above code written in OnChage event of the dropdown box in ASCX.Cs file so when use made selection and raise event it call this event and than custom register event. As you can see OnDropDownChange is called from the event and in turn custom written code of the page.

In following step we are going to utilize created custom control and the custom event


Step 4 : Use User control on page and utilize expose custom event .Aspx page
<%@ Register src="Controls/CommonDropDownControl.ascx" 
   tagname="CommonDropDownControl" tagprefix="uc" %>
    
    

code register the event which is going to be fire when the selection in dropdown box of user control change.


Step 5 : write code on page for the custom event .Aspx.CS file
protected void usrDrp_DrpChange(object sender, EventArgs e)
    {
        Response.Write("event called.");
    }
so last there is code of register custom event which get executed on change of dropdwon box of user control. Note that this code is written on the page where I am utilizing the control.

For referance full code of ascx.cs file
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
 
////////////////////////////////////////////////////////////////////////////////////
//
//    File Description  :  Common Dropdown box control
// ---------------------------------------------------------------------------------
//    Date Created            : Month DD, YYYY (Dec 01, 2011)
//    Author                      : Pranay Rana
// ---------------------------------------------------------------------------------
//    Change History
//    Date Modified           : Month DD, YYYY (e.g Jan 01, 2000)
//    Changed By        :
//    Change Description   :
//
/////////////////////////////////////////////////////////////////////////////////
public partial class ValidDropDown : System.Web.UI.UserControl
{
    #region property
    public string LableText
    {
        get
        {
            return lblText.Text;
        }
        set
        {
            lblText.Text = value;
        }
    }
   
    public bool IsRequired
    {
        get
        {
            return spnRequired.Visible;
        }
        set
        {
             valList.Visible = value;
            spnRequired.Visible = value;
        }
    }
    public bool Enabled
    {
        get
        {
            return ddlDropDown.Enabled;
        }
        set
        {
            ddlDropDown.Enabled = value;
        }
    }
    public int Count
    {
        get
        {
            return ddlDropDown.Items.Count;
        }      
    }
    public bool Clear
    {
        set
        {
            if (value)
            {
                ddlDropDown.Items.Clear();
                ddlDropDown.Items.Add(new ListItem(UIConstants.SELECT, "0"));
            }
        }
    }
  
    public string SelectedValue
    {
        get
        {
 
            return ddlDropDown.SelectedValue;
 
        }
        set
        {
            ddlDropDown.ClearSelection();
            ListItem li = ddlDropDown.Items.FindByValue(value.ToString());
            if (li != null)
                li.Selected = true;
        }
    }
    public ListItem SelectedItem
    {
        get
        {
 
            return ddlDropDown.SelectedItem;
 
        }
        set
        {
            ddlDropDown.ClearSelection();
            ListItem li = ddlDropDown.Items.FindByText(value.ToString());
            if (li != null)
                li.Selected = true;
        }
    }
    public string SelectedText
    {
        get
        {
 
            return ddlDropDown.SelectedItem.Text;
 
        }
        set
        {
            ddlDropDown.ClearSelection();
            ListItem li = ddlDropDown.Items.FindByText(value.ToString());
            if (li != null)
                li.Selected = true;
        }
    }
    public int SelectedIndex
    {
        get
        {
 
            return ddlDropDown.SelectedIndex;
 
        }
        set
        {
            ddlDropDown.SelectedIndex = value;
        }
    }
  
    public bool AutoPostBack
    {
        get
        {
            return ddlDropDown.AutoPostBack;
        }
        set
        {
            ddlDropDown.AutoPostBack = value;
        }
    }
    #endregion property
 
    #region public methods
 
    /// 
    /// Add Item to combo box
    /// 
    /// Name of the item

///  
Value of the item
public void AddItem(string pName, string pValue)
     {
         ddlDropDown.Items.Add(new ListItem(pName, pValue));
     }
         ///  


     /// Bind List to combo box , i.e data soruce for the combo box     
///
 
     /// Type of list 
     ///  
List of Items to bind///  
Name of the property display as text combo///  
Value Name of the property bind with the item
public void BindList(IList pLstItemInfo, string pDataText, string pDataValue)
     {
           ddlDropDown.ClearSelection();
         ddlDropDown.Items.Clear();
         if (pLstItemInfo != null)
         {
             ddlDropDown.DataSource = pLstItemInfo;
             ddlDropDown.DataTextField = pDataText;
             ddlDropDown.DataValueField = pDataValue;
             ddlDropDown.DataBind();
         }
           ddlDropDown.Items.Insert(0, new ListItem(UIConstants.SELECT, "0"));
       }       
#endregion public methods
         protected void Page_Load(object sender, EventArgs e)
     {
         if (!IsPostBack)
         {
             if (LableText == string.Empty)
                 tdLabel.Visible = false;
             if(ddlDropDown.Items.Count == 0)
                 ddlDropDown.Items.Add(new ListItem(UIConstants.SELECT, "0"));
         }
     }
         public event EventHandler DrpChange;
       public virtual void OnDropDownChange(
)     {
         if (DrpChange != null)
         {
             // CustomArgs  e = new CustomArgs(this.ddlDropDown);
             this.DrpChange(this, EventArgs.Empty);
         }
     }
     protected void ddlDropDown_SelectedIndexChanged(object sender, EventArgs e)
     {
         this.OnDropDownChange();
     }
 } 

Monday, January 16, 2012

Calling Server Side function from Client Side Script

The post is about how you can call your code behind file function i.e server side written function from your client side code i.e using jQuery.
Recently I got requirement in my project that I have to check that ApplicationCode i.e Value entered by user is already available in database or not i.e unique value.

Output of the will look like as below if record exists its shows error "Record exists" otherwise it doesn't display any record.

Now in following post I am going to discuss about the what are the prerequisite need and why to use that. 

Server Code
Below method get called from the client side script, as you can see there are some changes in the method attribute, declaration and definition which I am going to discuss
    [WebMethod]
    public static string IsExists(string value)
    {
        //code to check uniqe value call to database to check this
        return "True";
    }
WebMethod Attribute
Attached WebMethod attribute with Public method indicates that the method exposed as part of the XML Web service. The attribute tells .NET that a particular public method is exposed as a web-callable method. To make use of this attribute you need to make use of System.Web.Services You can read about this attribute at : WebMethodAttribute Class
Static method
Static method is not associated with the instance of the class which get called by using only classname.methodname() i.e no need to create instance.
So that's why I marked method as static one. It cannot interact with the instance properties and methods of your Page class, because a page method call creates no instance of the Page or any of its controls. Page methods are roughly equivalent to shorthand for standalone web services.

.CS file
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;//needed for the webmethod attribute
public

partial class _Default : System.Web.UI.Page
{
     protected void Page_Load(object sender, EventArgs e)
     {
          if (!IsPostBack)
               txtData.Attributes.Add("onblur", "focuslost()");
     }

     [WebMethod]
     public static string IsExists(string value)
     {
          return "True";
     }
}
in above code I have registered client event with onblur and attahced function focuslost.


Client Code on .ASPX page code
jQuery .ajax() call
To called method from the client side code I made use of the jQuery function called ajax to get more details about this function you can read about my blog post : Jquery Ajax Calling functions
function IsExists(pagePath, dataString, textboxid, errorlableid) {
 
$.ajax({
     type:"POST",
     url: pagePath,
     data: dataString,
     contentType:"application/json; charset=utf-8",
     dataType:"json",
     error:
          function(XMLHttpRequest, textStatus, errorThrown) {
               $(errorlableid).show();
               $(errorlableid).html("Error");
          },
     success:
          function(result) {
               var flg = true;
               if (result != null) {
                    flg = result.d;
                    if (flg == "True") {
                         $(errorlableid).show();
                    }
                    else {
                         $(errorlableid).hide();
                    }
          }
     }
    });
}
In client script :
As I have to check code is exists or not I attached focusout() event with my textbox control, so when the focus get lost it make ajax call to the TextChanged event of code behind file.
url -                Contains path of the page which is get called from the client side code i.e from aspx page.
data -              Data sent to server from the client it basically json string.
contentType - Content type sent to server.
dataType -      Expected data format from server
error -            Called when call to server method fails
success -         Called when call to server method is successes and return data from called method can be processed in this method
 .Aspx page code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Async="true" Inherits="_Default" %>








     
          

as in above code focuslost function get call IsExists function which in-turn call the serverside function and inform the entered value is unique or not.