I have 2 DropDownList
controls on my form, the second of which uses the SelectedValue
of the first as one of its binding parameters.
Both DropDownList
controls are in a FormView.InsertItemTemplate
with SelectedValue
properties bound to the FormView
's datasource using a Binding Expression.
The first time the FormView
renders in Insert mode, everything works fine. The problem is after an AutoPostBack
from the first DropDownList
, the FormView
doesn't (re-)bind, however since the ControlParameter
on the second DropDownList
has changed, it DOES bind (as intended), but an exception occurs on the Binding Expression of the second DDL, I assume since the FormView
is not binding on that pass:
System.InvalidOperationException: Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Here is the markup:
<InsertItemTemplate>
.
.
.
<tr class="GridViewRowB">
<td class="GridViewCell">
Offense Type
</td>
<td class="GridViewCell">
<asp:DropDownList ID="ddlOffenseType" runat="server" DataSourceID="dsOffenseType"
AutoPostBack="true" DataValueField="OffenseTypeID" DataTextField="Description"
SelectedValue='<%# Bind("OffenseTypeID") %>'>
</asp:DropDownList>
<asp:ObjectDataSource ID="dsOffenseType" runat="server" TypeName="OffenseType"
SelectMethod="GetAll">
<SelectParameters>
<asp:Parameter Name="ActiveOnly" DefaultValue="True" Type="Boolean" />
</SelectParameters>
</asp:ObjectDataSource>
</td>
</tr>
<tr class="GridViewRowA">
<td class="GridViewCell">
Attorney
</td>
<td class="GridViewCell">
<asp:DropDownList ID="ddlAttorney" runat="server" DataSourceID="dsAttorney" DataValueField="AttorneyID"
DataTextField="AttorneyNameWithCount" SelectedValue='<%# Bind("AttorneyID") %>'>
</asp:DropDownList>
<asp:ObjectDataSource ID="dsAttorney" runat="server" TypeName="Attorney"
SelectMethod="GetAttorneyWithCaseCount">
<SelectParameters>
<asp:Parameter Name="ActiveOnly" DefaultValue="True" Type="Boolean" />
<asp:ControlParameter Name="OffenseTypeID" Type="Int32" ControlID="ddlOffenseType"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
</td>
</tr>
.
.
.
</InsertItemTemplate>
My question is: What is the best way to make this functionality work? Is it possible to keep both DDL's inside the template? I would prefer to avoid using the AJAX toolkit or other client-side solutions.
This is an issue when we use cascading dropdownlist in Databinding Controls like DetailsView/FormView
and I have faced it many times. You have to remove the Binding Expression from your Second Dropdownlist SelectedValue='<%# Bind("AttorneyID") %>'
, then it will work.
Secondly if you remove the Binding expression, you have to pass the value manually in FormView ItemInserting
Event. e.g.
protected void frmAsset_ItemInserting(object sender, FormViewInsertEventArgs e)
{
eValues["AttorneyID"] = ((DropDownList)((FormView)sender).FindControl("ddlAttorny")).SelectedValue;
}
Actually I'm posting this answer in case anybody else got stuck like I did.
What Muhammad Akhtar said works perfectly, however I found a simpler solution.
In
<asp:DropDownList ID="ddlAttorney" runat="server" DataSourceID="dsAttorney" DataValueField="AttorneyID" DataTextField="AttorneyNameWithCount" SelectedValue='<%# Bind("AttorneyID") %>'>
change Bind("AttorneyID")
to DataBinder.Eval (Container.DataItem, "AttorneyID")
It works perfectly!
EDIT: My sample code:
<asp:Content ID="Content3" ContentPlaceHolderID="BodyContent" runat="Server">
<asp:DetailsView ID="dv" runat="server" Height="50px" DataSourceID="ODS" DefaultMode="Insert"
AutoGenerateRows="False" OnItemCommand="dv_ItemCommand" OnItemInserted="dv_ItemInserted"
DataKeyNames="Id" OnItemUpdated="dv_ItemUpdated" CssClass="DetailsView"
>
<Fields>
<asp:TemplateField HeaderText="Page Name:">
<ItemTemplate>
<asp:Label ID="txtPageName" runat="server" Text="<%#Bind('PageName') %>" />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtPageName" runat="server" Text="<%#Bind('PageName') %>" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Parent:">
<ItemTemplate>
<asp:Label ID="txtParentPageName" runat="server" Text='<%#Bind("ParentPageName") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList runat="server" ID="lstParentPage" DataSourceID="ParentPageODS"
AppendDataBoundItems="true" DataTextField="PageName" DataValueField="Id" SelectedValue="<%#Bind('ParentPage') %>"
AutoPostBack="True">
<asp:ListItem Text="-Root-" Value="" />
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="After...">
<ItemTemplate>
<asp:Label ID="txtPreviousPage" runat="server" Text='<%#Bind("PageOrder") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList runat="server" ID="lstPageOrder" AppendDataBoundItems="true" DataTextField="PageName" DataSourceID="PageOrderODS" DataValueField="PageOrder" EnableViewState="False" SelectedValue='<%# DataBinder.Eval (Container.DataItem, "PageOrder") %>'>
<asp:ListItem Text="-First-" Value="" />
</asp:DropDownList>
<asp:ObjectDataSource ID="PageOrderODS" runat="server" SelectMethod="SelectByParent"
TypeName="SirM2X.Pages">
<SelectParameters>
<asp:ControlParameter ControlID="lstParentPage" Name="ParentPage" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Dummy Page?">
<ItemTemplate>
<asp:Label runat="server" ID="txtDummyPage" Text="<%#Bind('IsDummyText') %>" />
</ItemTemplate>
<EditItemTemplate>
<asp:CheckBox ID="chkIsDummy" runat="server" Checked="<%#Bind('IsDummy') %>" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:Button ID="btnUpdate" runat="server" CausesValidation="True" CommandName="Update"
Text="<%$Resources:Resources, Update %>" />
<asp:Button ID="btnCancel" runat="server" CausesValidation="False" CommandName="Cancel"
Text="<%$Resources:Resources, Cancel %>" />
</EditItemTemplate>
<InsertItemTemplate>
<asp:Button ID="btnInsert" runat="server" CausesValidation="True" CommandName="Insert"
Text="<%$Resources:Resources, Insert %>" />
<asp:Button ID="btnCancel" runat="server" CausesValidation="False" CommandName="Cancel"
Text="<%$Resources:Resources, Cancel %>" />
</InsertItemTemplate>
<ItemTemplate>
<asp:Button ID="btnEdit" runat="server" CausesValidation="False" CommandName="Edit"
Text="<%$Resources:Resources, Edit %>" />
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
<asp:ObjectDataSource ID="ODS" runat="server" DeleteMethod="DeleteRow" InsertMethod="InsertRow"
SelectMethod="SelectRow" TypeName="SirM2X.Pages" UpdateMethod="UpdateRow" OnInserting="ODS_Inserting"
OnUpdating="ODS_Updating">
<DeleteParameters>
<asp:Parameter Name="Id" Type="Int32" />
</DeleteParameters>
<InsertParameters>
<asp:Parameter Name="PageName" Type="String" />
<asp:Parameter Name="CreatedBy" Type="String" />
<asp:Parameter Name="ParentPage" Type="Int32" />
<asp:Parameter Name="PageOrder" Type="Int32" />
<asp:Parameter Name="IsDummy" Type="Boolean" />
</InsertParameters>
<SelectParameters>
<asp:QueryStringParameter Name="Id" QueryStringField="ID" Type="Int32" />
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="Id" Type="Int32" />
<asp:Parameter Name="PageName" Type="String" />
<asp:Parameter Name="ParentPage" Type="Int32" />
<asp:Parameter Name="PageOrder" Type="Int32" />
<asp:Parameter Name="IsDummy" Type="Boolean" />
<asp:Parameter Name="DeleteState" Type="Boolean" />
</UpdateParameters>
</asp:ObjectDataSource>
<asp:ObjectDataSource ID="ParentPageODS" runat="server" SelectMethod="SelectAll"
TypeName="SirM2X.Pages"></asp:ObjectDataSource>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With