2008/09/30

Tips: Get the GridView control from the TextBox insides the GridView (7/21/09 updated)

Scenario:
1.You have one or more than one GridView(s) on your page.
2.Each GridView has one or more TextBox(s) in it.
3.At the TextChanged() event, you want to/have to know which GridView owns the event.
Here is the way to get the parent control of that TextBox:
//get the parent gridview
GridViewRow gvr = (GridViewRow)(((TextBox)sender).Parent).Parent;
GridView gv = (GridView)(gvr.Parent).Parent;

Once you get the GridViewRow, you can get the RowIndex value. Once you get the GridView, you get everything...

7/21/09 updated:
A better way to get the same thing by using NamingContainer property:
GridViewRow gvr = (GridViewRow)((TextBox)sender).NamingContainer;
GridView gv = (GridView)gvr.NamingContainer;

2008/09/21

Set the value of a DropDownList control by a given text or value

Usually we will set the default of a DropDownList control by using this command:

ddlCompany.SelectedIndex = 1;
However, what should we do if we only have a text string or a value of that text? For example, I want to bind this table to a DropDownList control:
ID  Name
--  -----
1   HP
2   IBM
3   Microsoft

And we want dynamically set the default value when the QueryString is presented, like http://xxxxxx/company.aspx?ID=2 or http://xxxxxx/company.aspx?Name=IBM.  In this scenario, we have to use the following codes to set the default value of the DropDownList control:

foreach (ListItem li in ddlCompany.Items)
{
if (li.Value == "2")
{
li.Selected = true;
break;
}
}
or

foreach (ListItem li in ddlCompany.Items)
{
if (li.Text == "IBM")
{
li.Selected = true;
break;
}
}

2008/09/15

Check dirty form: Server-Side (Code-Behind) method combines with Client-Side javascript

There are many ways to check whether the form is dirty or not, and most of them are client side (javascript) codes. My situation is:
1. I have to do a Server-Side condition check first, and then decide whether to call the client side javascript function.
2. My TextBox are all inside an UpdatePanel.

The pure client side solution (like this one) doesn't seem to be a good fit for me. The reason is because the "onunload" event will be called every time when a postback is fired, and the javascript confirm window will always show up. Here is my solution:

1. Setting a mark in the TextBox TextChanged event. This means the data has been modified by client.
protected void gvColumn1_TextChanged(object sender, EventArgs e)
{
  int tempValue;

  //check the input value
  if (int.TryParse(((TextBox)sender).Text, out tempValue))
  {
    //your logic here
    .....

    //here is the mark
    ViewState["DataChanged"] = true;
  }
  else
  {
    //your logic here
    .....
  }
}

2. Clear the mark at the click event of the "Save" button.
protected void btnSave_Click(object sender, EventArgs e)
{
  //your logic here
  .....

  if (ViewState["DataChanged"] != null)
    ViewState["DataChanged"] = null;
}

3. Check the mark if the "Exit", "Next Page", or "Previous Page" button is clicked. If the mark exists, call the javascript to show the confirm window.
protected void btnExit_Click(object sender, EventArgs e)
{
  if (ViewState["DataChanged"] != null && (bool)ViewState["DataChanged"]
    == true)
  {
    //your logic here
    .....

    //build the javascript script
    string script = "<script>";
    script += "if (confirm('Leave without saving your modifications?'))";
    script += "window.location='Default.aspx';";  //redirect to homepage
    script += "</script>";

    //giving user a chance to save before leaving
    ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
      "DataNotSave", script, false);
  }
  else
    Response.Redirect("~/Default.aspx");  //redirect to homepage
}

PS: This approach cannot solve the problem if users click the "Previous" or "Next" button on their browsers.