2011-07-19 12 views
5

Mam 2 DropDownList formantów w mojej formie, z których druga używa SelectedValue pierwszego z nich jako jednego z parametrów wiązania.Implementowanie kaskadowego wiązania DropDownList w szablonowej kontroli

Zarówno DropDownList steruje się za FormView.InsertItemTemplate z SelectedValue właściwościami związanymi z źródło danych FormView jest za pomocą Binding ekspresyjnych.

Po pierwszym renderowaniu FormView w trybie wstawiania wszystko działa poprawnie. Problem występuje po tym, jak AutoPostBack z pierwszego DropDownList, FormView nie wiąże się (ponownie), ale ponieważ zmienił się ControlParameter na drugim DropDownList, wiąże się (zgodnie z przeznaczeniem), ale występuje wyjątek w Wyrażeniu wiązania z drugi DLL, sądzę od FormView nie jest wiążące w tym przejściu:

System.InvalidOperationException metody Databinding jak Eval(), Xpath(), i wiązania() może być stosowany tylko w kontekście kontrolki databound .

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

Moje pytanie brzmi: Jaki jest najlepszy sposób, aby tę pracę funkcjonalność? Czy w szablonie można przechowywać oba pliki DDL? Wolałbym unikać używania zestawu narzędzi AJAX lub innych rozwiązań po stronie klienta.

Odpowiedz

8

Jest to problem, gdy używamy kaskadowej listy rozwijanej w formantach kontroli danych, takich jak DetailsView/FormView i wielokrotnie stawiałem temu czoła. Musisz usunąć wyrażenie wiążące z drugiej listy rozwijanej SelectedValue='<%# Bind("AttorneyID") %>', a następnie zadziała.

Po drugie, jeśli usuniesz wyrażenie wiążące, musisz przekazać wartość ręcznie w zdarzeniu FormView ItemInserting. na przykład

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

OK więc .... potem musiałby obsługiwać 'FormView .ItemInserting' i dodać parametr ręcznie? Co z tym samym problemem w trybie "Edycja"? Obsługuj ręcznie wartości początkowe i zaktualizowane? Przykładowy kod dla potomności zostałby doceniony. – pseudocoder

+0

yah, dokładnie. musisz zrobić to samo również w przypadku edycji. –

+0

Sprawdziłem, czy to rozwiązanie działa. Dzięki! Miałem kilka pomysłów podobnych do tego, ale nie byłem pewien, jak większość ludzi podchodzi do problemu. – pseudocoder

2

To może przyjść trochę późno, ale lepiej późno niż wcale:

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 

Przetestowałem to na imprezę ItemUpdating Urządzony widoku szczegółów, ale myślę, że będzie pracować dla FormView, tylko przełącznik potrzebne części i to zadziała.

Edit: Można sprawdzić to odniesienie: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview.itemupdating.aspx

4

Właściwie jestem delegowania tę odpowiedź w przypadku ktokolwiek inny utknął jak ja. To, co powiedział Muhammad Akhtar, działa idealnie, jednak znalazłem prostsze rozwiązanie.
W

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

zmiana Bind("AttorneyID") do DataBinder.Eval (Container.DataItem, "AttorneyID")
To działa doskonale!
EDIT: mój przykładowy kod:

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

+0

Czy możesz podać pełne źródło strony? Ten problem występuje tylko wtedy, gdy masz kaskadowanie elementów sterujących w szablonie, a moim zrozumieniem jest to, że DataBinder.Eval to w zasadzie to samo, co właśnie Eval. – pseudocoder

+0

@pseudocoder Myślałem, że robią to samo. Jednak ostatnio okazało się, że są one nieco inne w przypadku kaskadowych list rozwijanych. Załączam mój kod i działa on poprawnie. – M2X

1

Oto jak to zrobiłem ...

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