2011-06-17 90 views
1

我有一个中继器列出了客户项目,其中一个是用于获取更多信息的按钮。当用户点击该按钮时,用户控件就会出现在其下方。我希望用户控件在再次单击按钮时关闭。我最初切换了服务器端的可见性,但是现在我无法使用它,因为需要通过参数将用户控件加载到按钮单击上。我也不能使用jQuery显示和隐藏,因为这将涉及到整个页面首先下载所有数据,这可能会使页面太麻烦。FindControl无法找到我的动态添加的控件

所以目前在每个中继器我有命令参数和按需事件一个LinkBut​​ton的时候触发这个事件:

protected void uxPolicyDocsButton_Command(object sender, CommandEventArgs e) 
    { 
     //Find Policy Summary control within repeater item in order to toggle visibility 

     LinkButton button = sender as LinkButton; 
     if (button != null) 
     { 
      RepeaterItem ri = button.Parent as RepeaterItem; 

      if (ri != null) 
      { 
       PlaceHolder policySummaryPlaceHolder = (PlaceHolder)ri.FindControl("uxPolicySummaryPlaceHolder");      
       Control policyDocuments = (Control)PolicySummaryPlaceHolder.FindControl("uxPolicyDocumentsControl"); 


       foreach (Control c in policySummaryPlaceHolder.Controls) 
       { 
        //FindControl action goes in here. Have stepped through though and it doesn't appear 
       } 

       if (policyDocuments != null) 
       { 
        policySummaryPlaceHolder.Controls.Remove(policyDocuments); 
       } 
       else 
       { 
        policyDocuments uxPolicyDocumentsControl = (PolicyDocuments)LoadControl("~/Controls/Home/PolicyDocuments.ascx"); 
        uxPolicyDocumentsControl.PolicyNumber = button.CommandArgument; 
        policySummaryPlaceHolder.Controls.Add(uxPolicyDocumentsControl); 
       } 
      } 
     } 
    } 

我对切换计划是,如果PolicyDocuments控制为空,然后加载控制,如果没有,则删除该控件,但它总是返回null。它虽然正确加载控件。

这里是转发器的部分:

<ItemTemplate> 
        <tr> 
         <td> 
          <%#Eval("StartDate","{0:d}")%> 
         </td> 
         <td class="center-cell-ctrl"> 
          Postcode:<br /> 
          <%#Eval("Postcode")%> 
         </td> 
         <td id='<%#Eval("PolicyNumber")%>' class="button-cell">         
          <asp:LinkButton ID="uxPolicyDocsButton" CommandName="PolicyNumber" CommandArgument='<%#Eval("PolicyNumber")%>' OnCommand="uxPolicyDocsButton_Command" runat="server" Visible="false">Policy<br />Documents</asp:LinkButton> 
         </td> 
        </tr> 
        <asp:PlaceHolder ID="uxPolicySummaryPlaceHolder" runat="server"></asp:PlaceHolder> 
        <asp:PlaceHolder ID="uxPolicyDocumentsPlaceHolder" runat="server"></asp:PlaceHolder> 

     </ItemTemplate> 

我有一个到处寻找谁也有类似问题的人,和一个共同的答案是,你需要加载在Page_Init事件控制。这是否意味着这种方式不起作用?如果是这样的话,任何替代方案的想法?

非常感谢

+0

在用户控件中创建控件吗? – Andrew 2011-06-17 10:41:28

回答

1

我不明白”,为什么你不能添加PolicyDocumentsvisible = false并没有数据源,而不是Placeholder,这样的:

<uc:PolicyDocuments ID="uxPolicyDocuments" runat="server" Visible="false"></asp:PolicyDocuments> 

,并在命令使用这样的代码:

 if (ri != null) 
     { 
      var policyDocuments = ri.Controls.OfType<PolicyDocuments>().FirstOrDefault(); 
      if (policyDocuments == null) 
       return; 

      if (policyDocuments.Visible) 
      { 
       policyDocuments.Visible = false; 
      } 
      else 
      { 
       policyDocuments.PolicyNumber = button.CommandArgument; 
       policyDocuments.Visible = true; 
      } 
     } 

在这种情况下,你不需要在Init活动页面使用一些黑客。 无论如何,您始终可以使用.Controls.OfType<PolicyDocuments>()扩展方法来获取所需的所有用户控件。

3

每次你的页面加载时间(无论是最初,或通过回传)控制树需要被重新创建。

您的页面的ASPX部分中声明的控件由框架(种类)添加,但您添加的任何控件“动态”都需要放回控制树中。如果他们不是,那么就像你发现的那样,他们根本不能再被发现。

复杂的控件,如datagridview,通过在ViewState中存储(大量的)数据来重建其控制树。

它可能会更简单,而不是让您的页面添加/删除PlaceHolder中的项目,创建一个您可以隐藏的用户控件,并在第一次显示时加载它的数据。这也有助于你控制和页面坚持Single Repsonsibility Principal