<%@ Import Namespace="System.Data" %>
<%@ Register Src="Explanation.ascx" TagPrefix="wuc" TagName="Explanation" %>
<%@ Page Language="C#" AutoEventWireup="false" %>
<script language="C#" runat="server">
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
gvcascadingLists.RowUpdating += new GridViewUpdateEventHandler(gvcascadingLists_RowUpdating);
gvcascadingLists.RowCommand += new GridViewCommandEventHandler(gvcascadingLists_RowCommand);
gvcascadingLists.RowEditing += new GridViewEditEventHandler(gvcascadingLists_RowEditing);
Page.PreRender += new EventHandler(Page_PreRender);
}
//==============================================================================================
//The concept is basically to intercept the 2-way databinding within the RowUpdating event
//by passing into the GridViewUpdateEventArgs the new values that we need to update.
//This interception gives us the opportunity to set the selections for the cascading dropdownlist
//without relying on the Bind method to effect the 2-way databinding
//==============================================================================================
void gvcascadingLists_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string strCityID = ((DropDownList)((GridView)sender).Rows[e.RowIndex].FindControl("ddlCity")).SelectedValue;
e.NewValues["CityID"] = strCityID;
e.Cancel = false;
}
void AddEmptyItem(DropDownList ddl)
{
System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem("Make a Selection", "");
ddl.Items.Insert(0, li);
}
protected void ddlProvince_DataBound(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
//add an empty item on top of the list
AddEmptyItem(ddl);
GridViewRow gvRow = (GridViewRow)ddl.NamingContainer;
if (gvRow.DataItem != null)
{
string strProvinceID = ((DataRowView)gvRow.DataItem)["ProvinceID"].ToString();
//be careful of the possibility that the value saved on the
//database does not exist in the valid selections that are displayed
//on the list
ddl.ClearSelection();
System.Web.UI.WebControls.ListItem li = ddl.Items.FindByValue(strProvinceID);
if (li != null) li.Selected = true;
}
//since the city selection is cascading on the province, we
//have to databind the city list after we changed the selection for the province
ddl = (DropDownList)gvRow.FindControl("ddlCity");
if (ddl != null) ddl.DataBind();
}
protected void ddlCity_DataBound(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
//add an empty item on top of the list
AddEmptyItem(ddl);
ddl.SelectedIndex = 0;
GridViewRow gvRow = (GridViewRow)ddl.NamingContainer;
if (gvRow.DataItem != null)
{
string strCityID = ((DataRowView)gvRow.DataItem)["CityID"].ToString();
ddl.ClearSelection();
System.Web.UI.WebControls.ListItem lm = ddl.Items.FindByValue(strCityID);
if (lm != null) lm.Selected = true;
}
}
void gvcascadingLists_RowEditing(object sender, GridViewEditEventArgs e)
{
gvcascadingLists.EditIndex = e.NewEditIndex;
gvcascadingLists.DataBind();
}
void gvcascadingLists_RowCommand(object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "Cancel":
gvcascadingLists.EditIndex = -1;
gvcascadingLists.DataBind();
break;
}
}
void Page_PreRender(object sender, EventArgs e)
{
//in this event I am goin to add a little bit of Javascript
//to get the client ID of the Update LinkButton so that I execute
//an update postback when the user presses enter while editing any of the TextBoxes
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
Type cstype = this.GetType();
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(cstype, "UpdateIfEnterPressed"))
{
String cstext = null;
foreach (GridViewRow gvr in gvcascadingLists.Rows)
{
LinkButton lb = (LinkButton)gvr.FindControl("btnUpdate");
if (lb != null)
{
cstext = "document.onkeypress=function(evt) { " + Environment.NewLine;
cstext += "var a=document.getElementById(\"" + lb.ClientID + "\");" + Environment.NewLine;
cstext += "var returnPressed=false;" + Environment.NewLine;
cstext += "if (window.event) returnPressed=window.event.keyCode==13;" + Environment.NewLine;
cstext += "else returnPressed=evt.charCode==13;" + Environment.NewLine;
cstext += "if (returnPressed) { event.returnValue=false;event.cancelBubble=true; eval(a.href);} }" + Environment.NewLine;
cs.RegisterStartupScript(cstype, "UpdateIfEnterPressed", cstext, true);
break;
}
}
}
}
</script>
<asp:content id="Content1" runat="server" contentplaceholderid="MainContent">
<table>
<tr>
<td>
<h3>
Demo for 2-way databinding cascading lists within a GridView</h3>
<asp:GridView ID="gvcascadingLists" runat="server" DataSourceID="odsAddresses" AllowPaging="True"
AutoGenerateColumns='false' DataKeyNames="PK_ID">
<EmptyDataTemplate>
No Data is available
</EmptyDataTemplate>
<Columns>
<%-- instead of using a CommandField with ShowEditButton=true, I will use
the equivalent in a TemplateField. Any LinkButton with CommandName set to Edit
Cancel or Update will trigger the equivalent events as those 3 buttons produced
from a CommandField. The difference is the ability to get the ID of each of those
button so that when the user presses the Enter key I can trigger one of them
separate from the others --%>
<asp:TemplateField HeaderText="Commands">
<ItemTemplate>
<asp:LinkButton CommandName="Edit" ID="btnEdit" runat="server" Text="Edit"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton CommandName="Update" ID="btnUpdate" runat="server" Text="Update"></asp:LinkButton>
<asp:LinkButton CommandName="Cancel" CausesValidation="False" ID="btnCancel" runat="server" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Company Name">
<ItemTemplate>
<asp:Label ID="lblCompany" runat="server" Text='<%# Eval("Company") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtCompany" runat="server" Text='<%# Bind("Company") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Street Address">
<ItemTemplate>
<asp:Label ID="lblStreet" runat="server" Text='<%# Eval("Street") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtStreet" runat="server" Text='<%#Bind("Street") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Country">
<ItemTemplate>
<asp:Label ID="lblCountry" runat="server" Text='<%#Eval("Country") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:ObjectDataSource ID="odsCountries" runat="server" SelectMethod="CountryList"
TypeName="WEBSWAPP_BLL.Demos"></asp:ObjectDataSource>
<asp:DropDownList ID="ddlCountry" runat="server" DataSourceID="odsCountries" AutoPostBack="True"
SelectedValue='<%# Eval("CountryID") %>' DataTextField="Description" DataValueField="PK_ID">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Province">
<ItemTemplate>
<asp:Label ID="lblProvince" runat="server" Text='<%#Eval ("Province") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:ObjectDataSource ID="odsProvinces" runat="server" SelectMethod="ProvincesList"
TypeName="WEBSWAPP_BLL.Demos">
<SelectParameters>
<asp:ControlParameter ControlID="ddlCountry" Name="CountryID" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
<asp:DropDownList ID="ddlProvince" runat="server" DataSourceID="odsProvinces" AutoPostBack="true"
OnDataBound="ddlProvince_DataBound" DataTextField="Description" DataValueField="PK_ID">
</asp:DropDownList>
<asp:RequiredFieldValidator ForeColor="white" ID="valddlProvince" runat="server"
ErrorMessage="Cannot leave the province selection blank" Text="*" Display="Dynamic"
ControlToValidate="ddlProvince"></asp:RequiredFieldValidator>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City">
<ItemTemplate>
<asp:Label ID="lblCity" runat="server" Text='<%#Eval("City") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:ObjectDataSource ID="odsCities" runat="server" SelectMethod="CitiesList" TypeName="WEBSWAPP_BLL.Demos">
<SelectParameters>
<asp:ControlParameter ControlID="ddlProvince" Name="ProvinceID" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
<asp:DropDownList ID="ddlCity" runat="server" DataSourceID="odsCities" DataTextField="Description"
DataValueField="PK_ID" OnDataBound="ddlCity_DataBound">
</asp:DropDownList>
<asp:RequiredFieldValidator ForeColor="white" ID="valddlCity" runat="server" ErrorMessage="Cannot leave the city selection blank"
Text="*" Display="Dynamic" ControlToValidate="ddlCity"></asp:RequiredFieldValidator>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsAddresses" runat="server" SelectMethod="Contacts" TypeName="WEBSWAPP_BLL.Demos"
UpdateMethod="UpdateContact">
<UpdateParameters>
<asp:Parameter Name="PK_ID" Type="Int32" />
<asp:Parameter Name="Company" Type="String" />
<asp:Parameter Name="Street" Type="String" />
<asp:Parameter Name="CityID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
<%-- let's add a summary validation control to display a pop up message --%>
<asp:ValidationSummary ID="valSumm" runat="server" ShowMessageBox="true" ShowSummary="false" />
<%-- Let's add a label to display any status--%>
<asp:Label ID="lblStatus" runat="server" EnableViewState="false" CssClass="ErrMessage"></asp:Label>
</td>
</tr>
</table>
<wuc:Explanation ID="Explanation1" runat="server"></wuc:Explanation>
</asp:content>