【问题标题】:Implementing cascading DropDownList binding in a templated control在模板化控件中实现级联 DropDownList 绑定
【发布时间】:2011-07-19 15:38:17
【问题描述】:

我的表单上有 2 个DropDownList 控件,其中第二个使用第一个的SelectedValue 作为其绑定参数之一。

两个DropDownList 控件都在FormView.InsertItemTemplate 中,SelectedValue 属性使用绑定表达式绑定到FormView 的数据源。

FormView 第一次以插入模式呈现时,一切正常。问题是在第一个DropDownListAutoPostBack 之后,FormView 不会(重新)绑定,但是由于第二个DropDownList 上的ControlParameter 已更改,它确实绑定(按预期) ,但第二个 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 工具包或其他客户端解决方案。

【问题讨论】:

    标签: asp.net drop-down-menu formview


    【解决方案1】:

    当我们在像DetailsView/FormView 这样的数据绑定控件中使用级联下拉列表时,这是一个问题,我已经遇到过很多次了。您必须从第二个下拉列表SelectedValue='&lt;%# Bind("AttorneyID") %&gt;' 中删除绑定表达式,然后它才会起作用。

    其次,如果你删除了Binding表达式,你必须在FormViewItemInserting事件中手动传递值。例如

     protected void frmAsset_ItemInserting(object sender, FormViewInsertEventArgs e)
     {
        eValues["AttorneyID"] = ((DropDownList)((FormView)sender).FindControl("ddlAttorny")).SelectedValue;
     }
    

    【讨论】:

    • OK 所以....那么我需要处理FormView.ItemInserting 并手动添加参数? Edit 模式下同样的问题呢?手动处理初始值和更新值?后代的示例代码将不胜感激。
    • 我验证了这个解决方案有效。谢谢!我有一些类似的想法,但不确定大多数人如何解决这个问题。
    • 我多年来一直在使用这种方法,自从我开始使用它以来,我在互联网上搜索了很多,除了我提供给您的解决方案之外找不到其他解决方案。
    【解决方案2】:

    实际上,我正在发布此答案,以防其他人像我一样陷入困境。 Muhammad Akhtar 所说的非常有效,但是我找到了一个更简单的解决方案。

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

    【讨论】:

    • 能否给出整页源码?仅当您在模板中有级联控件时才会出现此问题,我的理解是 DataBinder.Eval 本质上与 Eval 相同。
    • @pseudocoder 我认为他们做同样的事情。但是,最近我发现它们在级联下拉列表的情况下略有不同。我已附上我的代码,它运行良好。
    【解决方案3】:

    这可能来得有点晚,但迟到总比没有好:

    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

    【讨论】:

      【解决方案4】:

      我是这样做的……

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

      【讨论】:

        猜你喜欢
        • 2015-10-27
        • 2022-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-08
        • 2011-06-06
        • 1970-01-01
        相关资源
        最近更新 更多