Реализация каскадной привязки DropDownList в шаблонном элементе управления

В моей форме есть 2 DropDownList элемента управления, второй из которых использует SelectedValue первого в качестве одного из параметров привязки.

Оба DropDownList элемента управления находятся в FormView.InsertItemTemplate со свойствами SelectedValue, привязанными к источнику данных FormView с помощью выражения привязки.

При первом рендеринге FormView в режиме вставки все работает нормально. Проблема в том, что после AutoPostBack из первого DropDownList FormView не (повторно) связывается, однако, поскольку ControlParameter во втором DropDownList изменилось, он ДЕЙСТВИТЕЛЬНО связывает (как и предполагалось), но возникает исключение в выражении привязки для второй DDL, как я предполагаю, поскольку FormView не привязан к этому проходу:

System.InvalidOperationException: методы привязки данных, такие как Eval (), XPath () и Bind (), могут использоваться только в контексте элемента управления привязкой к данным.

Вот разметка:

<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>

Мой вопрос: как лучше всего заставить эту функцию работать? Можно ли сохранить оба DDL в шаблоне? Я бы предпочел избегать использования набора инструментов AJAX или других клиентских решений.


person pseudocoder    schedule 19.07.2011    source источник


Ответы (4)


Это проблема, когда мы используем каскадный раскрывающийся список в элементах управления привязкой данных, таких как DetailsView/FormView, и я сталкивался с этим много раз. Вам нужно удалить выражение привязки из второго раскрывающегося списка SelectedValue='<%# Bind("AttorneyID") %>', тогда оно будет работать.

Во-вторых, если вы удалите выражение привязки, вам придется вручную передать значение в FormView ItemInserting Event. например

 protected void frmAsset_ItemInserting(object sender, FormViewInsertEventArgs e)
 {
    eValues["AttorneyID"] = ((DropDownList)((FormView)sender).FindControl("ddlAttorny")).SelectedValue;
 }
person Muhammad Akhtar    schedule 19.07.2011
comment
Хорошо, так .... тогда мне нужно будет обработать FormView.ItemInserting и добавить параметр вручную? А как насчет той же проблемы в режиме Edit? Обрабатывать как начальные, так и обновленные значения вручную? Был бы признателен пример кода для потомков. - person pseudocoder; 19.07.2011
comment
Я убедился, что это решение работает. Спасибо! У меня были похожие идеи, но я не знал, как большинство людей подходят к этой проблеме. - person pseudocoder; 19.07.2011
comment
Я использую этот подход на протяжении многих лет, с тех пор как я начал его использовать, я много искал в Интернете и не мог найти другого решения, кроме того, что я вам предоставил. - person Muhammad Akhtar; 19.07.2011

На самом деле я отправляю этот ответ на случай, если кто-то застрял, как я. То, что сказал Мухаммад Ахтар, прекрасно работает, однако я нашел более простое решение.
В

<asp:DropDownList ID="ddlAttorney" runat="server" DataSourceID="dsAttorney" DataValueField="AttorneyID" DataTextField="AttorneyNameWithCount" SelectedValue='<%# Bind("AttorneyID") %>'>

измените Bind("AttorneyID") на DataBinder.Eval (Container.DataItem, "AttorneyID")
Он отлично работает!
РЕДАКТИРОВАТЬ: Мой пример кода:

<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 %>" />
                &nbsp;<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 %>" />
                &nbsp;<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>

person Maghoumi    schedule 17.07.2012
comment
Можете дать полный исходник страницы? Эта проблема возникает только тогда, когда у вас есть каскадные элементы управления в шаблоне, и я понимаю, что DataBinder.Eval по сути то же самое, что и просто Eval. - person pseudocoder; 19.07.2012
comment
@pseudocoder Я думал, они делают то же самое. Однако недавно я обнаружил, что в случае каскадных выпадающих списков они немного отличаются. Я прикрепил свой код, и он отлично работает. - person Maghoumi; 19.07.2012

Это может произойти немного поздно, но лучше поздно, чем никогда:

Protected Sub DetailsView1_ItemUpdating(sender As Object, e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
  e.NewValues("AtendeeSubType") = DirectCast(DirectCast(sender, DetailsView).FindControl("dropdownlist3"), DropDownList).SelectedValue
End Sub

Я тестировал это для события ItemUpdating представления подробностей, но я думаю, что он будет работать для представления формы, просто переключите нужные части, и он будет работать.

Изменить: вы можете проверить эту ссылку: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview.itemupdating.aspx

person apereira    schedule 01.03.2012

Вот как я это сделал ...

<asp:SqlDataSource ID="sqldsDDPlant" runat="server" ConnectionString="<%$ ConnectionStrings:SeedTrackerConnectionString %>" 
    SelectCommand="SELECT * FROM [Plant] ORDER BY [Plant]"></asp:SqlDataSource>

<asp:SqlDataSource ID="sqldsDDType" runat="server" ConnectionString="<%$ ConnectionStrings:SeedTrackerConnectionString %>" 
    SelectCommand="SELECT * FROM [Type] ORDER BY [Type]" FilterExpression="PLID = '{0}'">
        <FilterParameters>
            <asp:ControlParameter Name="plantParam" ControlID="DVSeedTracker$ddPlant" PropertyName="SelectedValue" />
        </FilterParameters>  
</asp:SqlDataSource>

        <asp:TemplateField HeaderText="Plant">
            <InsertItemTemplate>
                <asp:DropDownList ID="ddPlant" runat="server" AutoPostBack="true" SelectedValue='<%# Bind("PLID") %>'
                 DataSourceID="sqldsDDPlant"  DataTextField="Plant" DataValueField="PLID" AppendDataBoundItems="True">
                    <asp:ListItem></asp:ListItem>
                </asp:DropDownList>
                 <asp:RequiredFieldValidator
                    id="RequiredFieldValidator2"
                    runat="server"
                    ControlToValidate="ddPlant"
                    Display="Static"
                    ErrorMessage="*Required" CssClass="RequiredField" />                
            </InsertItemTemplate>
        </asp:TemplateField>

        <asp:TemplateField HeaderText="Type">
            <InsertItemTemplate>
                <asp:DropDownList ID="ddType" runat="server"
                DataSourceID="sqldsDDType"  DataTextField="Type" DataValueField="TYPID" AppendDataBoundItems="False">
                    <asp:ListItem></asp:ListItem>
                </asp:DropDownList>
                    <asp:RequiredFieldValidator
                    id="RequiredFieldValidator3"
                    runat="server"
                    ControlToValidate="ddType"
                    Display="Static"
                    ErrorMessage="*Required" CssClass="RequiredField" />                                   
            </InsertItemTemplate>
        </asp:TemplateField>
person AGH    schedule 13.09.2012