<%@ Import Namespace="System.Data" %>
<%@ Page Language="VB" AutoEventWireup="false" %>
<script language="VB" runat="server">
Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
MyBase.OnInit(e)
AddHandler gvcascadingLists.RowUpdating, AddressOf gvcascadingLists_RowUpdating
AddHandler gvcascadingLists.RowEditing, AddressOf gvcascadingLists_RowEditing
AddHandler Page.PreRender , AddressOf Page_PreRender
End Sub
'==============================================================================================
'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
'==============================================================================================
Protected Sub gvcascadingLists_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs)
Dim strCityID As String = DirectCast(DirectCast(sender, GridView).Rows(e.RowIndex).FindControl("ddlCity"), DropDownList).SelectedValue
e.NewValues("CityID") = strCityID
e.Cancel = False
End Sub
Protected Sub AddEmptyItem(ByVal ddl As DropDownList)
Dim li As New System.Web.UI.WebControls.ListItem("Make a Selection", "")
ddl.Items.Insert(0, li)
End Sub
Protected Sub ddlProvince_DataBound(ByVal sender As Object, ByVal e As EventArgs)
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
'=== add an empty item on top of the list
AddEmptyItem(ddl)
Dim gvRow As GridViewRow = DirectCast(ddl.NamingContainer, GridViewRow)
If Not gvRow.DataItem Is Nothing Then
Dim strProvinceID As String = DirectCast(gvRow.DataItem, DataRowView)("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()
Dim li As System.Web.UI.WebControls.ListItem = ddl.Items.FindByValue(strProvinceID)
If Not li Is Nothing Then li.Selected = True
End If
'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 = DirectCast(gvRow.FindControl("ddlCity"), DropDownList)
If Not ddl Is Nothing Then ddl.DataBind()
End Sub
Protected Sub ddlCity_DataBound(ByVal sender As Object, ByVal e As EventArgs)
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
'add an empty item on top of the list
AddEmptyItem(ddl)
ddl.SelectedIndex = 0
Dim gvRow As GridViewRow = DirectCast(ddl.NamingContainer, GridViewRow)
If Not gvRow.DataItem Is Nothing Then
Dim strCityID As String = DirectCast(gvRow.DataItem, DataRowView)("CityID").ToString
ddl.ClearSelection()
Dim li As System.Web.UI.WebControls.ListItem = ddl.Items.FindByValue(strCityID)
If Not li Is Nothing Then li.Selected = True
End If
End Sub
Protected Sub gvcascadingLists_RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
gvcascadingLists.EditIndex = e.NewEditIndex
gvcascadingLists.DataBind()
End Sub
Protected Sub gvcascadingLists_RowCommnad(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
Select Case e.CommandName
Case "Cancel"
gvcascadingLists.EditIndex = -1
gvcascadingLists.DataBind()
End Select
End Sub
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
'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.
Dim cs As ClientScriptManager = Page.ClientScript
Dim csType As Type = Me.GetType
'Check to see if the startup script is already registered.
If Not cs.IsStartupScriptRegistered(csType, "UpdateIfEnterPressed") Then
Dim cstext As String = String.Empty
For Each gvr As GridViewRow In gvcascadingLists.Rows
Dim lb As LinkButton = DirectCast(gvr.FindControl("btnUpdate"), LinkButton)
If Not lb Is Nothing Then
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)
Exit For
End If
Next
End If
End Sub
</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>
<tr>
<td>
<br />
<br />
This sample of the GridView is using the same concepts that were demonstrated on
the FormView in the other demo within this section.
<br />
<br />
<p>
</p>
</td>
</tr>
</table>
</asp:Content>