2009-09-03 134 views
0

我有以下嵌套結構。我需要的是根據RadioButtonList選項的值從後面的CustomControl1代碼中過濾一個DB Linq查詢。如何從嵌套內部控件查找外部控件

x MainPage1 
x---- Panel1 (modal popup) 
x--------- UpdatePanel (upMailOrStatusAction, on Panel1) 
x-------------- RadioButtonList (rblActionLevel, on UpdatePanel) 
x-------------- SubForm1 (on Panel1) 
x------------------- CustomControl1 (on Subform1) 
x------------------------ DropDownList (on CustomControl1) 

我想類似下面找到了控制,但它說:「‘upMailOrStatusAction’這個名字不會在目前情況下存在。

RadioButtonList rbl = upMailOrStatusAction.FindControl("rblActionLevel") as RadioButtonList; 

什麼是找到最好的辦法?!RadioButtonList控件是的,我與這個相當新

謝謝 吉姆薩瓦尼,GA

好,這裏是彈出ASPX:

  <asp:Panel ID="pnlAddMailOrStatusAction" runat="server" CssClass="modalPopupLarge" Style="display: none;"> 
      <asp:UpdatePanel ID="upMailOrStatusAction" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false" RenderMode="Block"> 
       <Triggers> 
        <asp:AsyncPostBackTrigger ControlID="rblActionType" /> 
       </Triggers> 
       <ContentTemplate> 
        <div class="borderDiv"> 
         <table class="borderTable0" cellpadding="0" cellspacing="0" width="100%"> 
          <thead> 
           <tr align="left"> 
            <th colspan="9">Action Detail</th> 
           </tr> 
          </thead> 
          <tbody> 
           <tr> 
            <td colspan="1"> 
             <label class="labelfield">Action Level:</label> 
            </td> 
            <td colspan="1" rowspan="1" align="left"> 
             <asp:RadioButtonList ID="rblActionLevel" runat="server" AutoPostBack="True" RepeatDirection="Horizontal" 
              RepeatLayout="Flow"> 
              <asp:ListItem Selected="True" Value="Base" Text="Base&nbsp;&nbsp;" /> 
              <asp:ListItem Value="Coverage" Text="Coverage" /> 
             </asp:RadioButtonList> 
            </td> 
            <td colspan="1" align="left"> 
             <asp:Label ID="lblMSCoverage" runat="server" class="labelfield" Text="Coverage:" /> 
            </td> 
            <td colspan="1" align="left"> 
             <asp:Label ID="txtMSCoverage" runat="server" /> 
            </td> 
            <td colspan="5"> 
             &nbsp; 
            </td> 
           </tr> 
           <tr> 
            <td colspan="9"> 
             <hr /> 
            </td> 
           </tr> 
           <tr> 
            <td colspan="9"> 
            <st:MailAddSubform runat="server" ID="mailAddSubform" /> 
            <st:StatusActionAddSubform runat="server" ID="statusActionAddSubform" Visible="false" /> 
            </td> 
           </tr> 
           <tr> 
            <td colspan="9"> 
             <hr /> 
            </td> 
           </tr> 
          </tbody>  
         </table> 
        </div> 
       </ContentTemplate> 
      </asp:UpdatePanel> 
     </asp:Panel> 

這裏是子窗體的aspx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MailAddSubform.ascx.cs" 
Inherits="Company.Solutions.Web.Controls.MailAddSubform" %> 
操作: 消息: 這裏是自定義控件的aspx: 過濾器

最後,這裏是背後的定製控件的代碼。查找StackOverflow以查找單選按鈕列表:

using System; 
using System.Collections.Generic; 
using System.Collections; 
using System.Configuration; 
using System.Data; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Web; 
using System.Web.Security; 
using System.Web.UI; 
using System.Web.UI.HtmlControls; 
using System.Web.UI.WebControls; 
using System.Web.UI.WebControls.WebParts; 
using System.Xml.Linq; 
using Company.Solutions.Data; 
using Company.Solutions.Data.Model; 
using Company.Solutions.Business.ViewModels; 
using Company.Solutions.Business.Helpers; 


namespace Comapny.Solutions.Web.Controls 
{ 
    public partial class StMailActionLookup : System.Web.UI.UserControl 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      BindForm(); 
     } 

     protected void BindForm() 
     { 
      IEnumerable actions = GetClaimMailActions(GetFilter()); 
      ddlLookup.DataSource = actions; 
      ddlLookup.DataTextField = "CodeAndDescription"; 
      ddlLookup.DataValueField = "actionCd"; 
      ddlLookup.DataBind(); 
     } 

     //protected void ddlLookup_DataBound1(object sender, System.EventArgs e) 
     //{ 
     // ddlLookup.Items.Insert(0, new ListItem("<Please Choose an Action>", String.Empty)); 
     //} 

     private MailActionFilters GetFilter() 
     { 
      MailActionFilters filters = new MailActionFilters(); 
      if (chkForms.Checked) 
        filters |= MailActionFilters.Forms; 
      if (chkRequested.Checked) 
        filters |= MailActionFilters.RequestedInfo; 
      if (chkOther.Checked) 
        filters |= MailActionFilters.Other; 

      return filters; 
     } 

     public IEnumerable GetClaimMailActions(MailActionFilters filter) 
     { 
      RelationalDataContext db = RelationalDataContext.Create(); 
      List<Expression<Func<ClaimMailAction, bool>>> predicates = new List<Expression<Func<ClaimMailAction, bool>>>(); 

      const string MAIL_ACTIONS = "0"; 
      const char FORMS = 'F'; 
      const char REQUESTED_INFO = 'R'; 
      const char EXCLUDE = 'X'; 



      //StackOverflow help 

      //RadioButtonList rbl = (RadioButtonList) Control.Parent.FindControl("rblActionLevel"); 




      if ((!chkForms.Checked && !chkRequested.Checked && !chkOther.Checked) | (chkForms.Checked && chkRequested.Checked && chkOther.Checked)) 
      { 
       predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && (cma.EsolutionsCode == null || cma.EsolutionsCode!= EXCLUDE)); 
      } else { 

       if((filter & MailActionFilters.Forms) == MailActionFilters.Forms) 
        predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && cma.EsolutionsCode == FORMS); 

       if((filter & MailActionFilters.RequestedInfo) == MailActionFilters.RequestedInfo) 
        predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && cma.EsolutionsCode == REQUESTED_INFO); 

       if((filter & MailActionFilters.Other) == MailActionFilters.Other) 
        predicates.Add(cma => cma.ActionCd.StartsWith(MAIL_ACTIONS) && (cma.EsolutionsCode == null || (cma.EsolutionsCode != EXCLUDE && cma.EsolutionsCode != FORMS && cma.EsolutionsCode != REQUESTED_INFO))); 
      } 

      var predicate = PredicateBuilder.Make<ClaimMailAction>(); 
      predicates.ForEach(delegate(Expression<Func<ClaimMailAction, bool>> expr) 
      { 
       predicate = predicate.Or(expr); 
      }); 

      var qry = db.ClaimMailActions.Where(predicate).Select(c => new { c.ActionCd, CodeAndDescription = string.Format("{0} - {1}", c.ActionCd, c.ActionDesc) }); 

      return qry.ToList(); 
     } 
    } 
} 

新的代碼列表。我的同事將這個用於另一個查找。有人能告訴我如何爲這個查找做類似的事嗎?即使效率低下,如果它的效果如此。

HtmlForm form; 



     foreach(var ctl in Page.Controls[0].Controls) 

     { 

      if(ctl is HtmlForm) 

      { 

       form = ctl as HtmlForm; 

       ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder; 

       if (holder != null) 

       { 

        PlaceHolder paymentControlHolder = holder.FindControl("plcPaymentForm") as PlaceHolder; 

        if (paymentControlHolder != null) 

        { 

         IListener listener; 

         foreach (var c in paymentControlHolder.Controls) 

         { 

          if (c is IListener) 

          { 

           listener = c as IListener; 

           rblPaymentType.SelectedIndexChanged += listener.AddHandler(); 

          } 

         } 

        } 

       } 





      } 

     } 

好吧,我想這一點,但還沒有完全想通了,但如何確定單選按鈕的選定值:

HtmlForm form; 
     foreach (var ctl in Page.Controls[0].Controls) { 
      if (ctl is HtmlForm) { 
       form = ctl as HtmlForm; 
       ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder; 
       if (holder != null) { 
        RadioButtonList rblControlHolder = holder.FindControl("rblActionLevel") as RadioButtonList; 
        if (rblControlHolder != null) { 

        } 
       } 
      } 
     } 

回答

2

我不知道是否我完全理解你想要達到的目標。但是如果你想在你的頁面上找到控件,你可能需要一個解決方案,因爲我發佈了here

public static Control FindControlRecursive(Control parent, string controlId) 
{ 
    if (controlId == parent.ID) 
     return parent; 

    foreach (Control ctrl in parent.Controls) 
    { 
     Control tmp = FindControlRecursive(ctrl, controlId); 
     if (tmp != null) 
      return tmp; 
    } 

    return null; 
} 

它是標準查找控件的遞歸實現。但明智地選擇你的父母。如果你有一個大的頁面,並且你指出這是搜索根目錄,那麼它將遍歷頁面的所有控件,直到最深的嵌套控件。您也可以採用相反的方式,基本上從您的控制開始,遞歸地上升,直到達到頁面級別。將是另一種選擇。

我發現這個遞歸發現的唯一問題是,當你的頁面上有一箇中繼器時,你可能會遇到問題。你不應該穿過中繼器的內部控制。由於其架構有一些問題,否則將會失去視圖狀態。一旦我有空,我會發布這個遞歸方法的更新。

編輯:
你得到的單選按鈕的選定條目,如下所示:

RadioButtonList myInstance = //find my radio button list 
string selectedValue = myInstance.SelectedValue; 
+0

Juri, 目標僅僅是確定單選按鈕值,以便我可以修改我的查詢以相應地填充下拉列表。我會嘗試你的查詢以及它可能派上用場。 謝謝! Jim – James 2009-09-03 12:58:22

+0

如果你的radiobuttonlist在你的用戶控件或頁面上,你應該可以直接訪問它,不是嗎?或者至少是它的容器元素。我真的不明白爲什麼你必須從頁面向下遍歷所有內容。 – Juri 2009-09-03 13:08:01

+0

順便說一句,下面的代碼可以通過調用我的FindControlRecursive(this.Page,「rblActionLevel」)作爲RadioButtonList來解決,儘管我仍然堅信有一個簡單的方法。 – Juri 2009-09-03 13:08:50

0

使用屬性Parent,使自己的方式控制樹。

CustomControl1.Parent.Parent.Parent.FindControl("rblActionLevel"); 
+0

好吧,我明白了,但我在自定義控制的代碼背後的定義是這樣的: 公共部分類StMailActionLookup:System.Web.UI.UserControl 而且我得到「一個對象引用是必需的非靜態字段,方法或屬性'System.Web.UI.Control.Parent.Get' 使用以下內容: RadioButtonList rbl =(RadioButtonList)StMailActionLookup.Parent.FindControl(「rblActionLevel」); – James 2009-09-03 03:53:25

+0

這是自定義控件如何從子窗體中定義的:

James 2009-09-03 04:05:10

+0

爲什麼不張貼你的整個表格,以便我們可以分析結構。 – ChaosPandion 2009-09-03 04:14:17

0

捎帶混沌...

RadioButtonList rbl = (RadioButtonList)Control.Parent.FindControl("rblActionLevel") 
0

「的對象引用是所必需的非靜態字段,方法或屬性「System.Web.UI.Control.Parent。獲取」使用下面的:單選按鈕列表RBL =(單選按鈕列表)StMailActionLookup.Parent.FindControl( 「rblActionLevel」);

你引用的對象類型 「StMailActionLookup」 時,你應該參考「郵件ActionLookup「,這是控件實例的ID。

這樣的代碼看起來像:

RadioButtonList rbl = (RadioButtonList) mailActionLookup.Parent.FindControl("rblActionLevel"); 

不知道,如果這是你想出了,但只是一個小的修正代碼中的問題。

另外,請記住UpdatePanel是一個模板化的控件,RadioButtonList和所有其他控件都在UpdatePanels生命週期某處的ContentTemplateContainer中呈現(我認爲它在CreateChildControls周圍的某處)。它取決於你從哪裏調用BindForm()方法,但可能是因爲RadioButtonList在你試圖找到它的時候確實不可用。即使它在標記中,模板中的控件也不會像標記中的其他控件一樣創建。他們有點怪異的野獸。

對於測試,嘗試在重寫的Render方法或類似的東西中運行查找控制代碼。通過Render方法,你可以保證所有的控件都可用。

public override Render(HtmlTextWriter writer) { 
    RadioButtonList rbl = (RadioButtonList)upMailOrStatusAction.FindControl("rblActionLevel"); 
} 

此外,由於upMailOrStatusAction是一個UpdatePanel,代碼可能是

upMailOrStatusAction.ContentTemplateContainer.FindControl("rblActionLevel"); 
+0

對於你的第一個代碼示例「mailActionLookup」和第二個示例「upMailOrStatusAction」,我得到了「該名稱在當前上下文中不存在」的錯誤,每個錯誤都引用這個引號中的字段。我還沒有嘗試渲染,但我會。謝謝, Jim – James 2009-09-03 05:34:49

+0

是的,對不起,我應該仔細閱讀代碼。 mailActionLookup是RadioButtonList的兄弟(完全錯過了),因此編寫非脆弱的代碼很困難。最好的辦法是啓動頁面,並按照radiobuttonlist的層次結構進行遞歸搜索。 Page.FindControl不會執行這個技巧,因爲它只有一層深度。你需要在網上找到一個輔助方法。 或者,您可以正確使用從mailActionControl開始的幫助程序方法,並且可以搜索每個父控件的控件集合。但兩者效率都很低。 – JayRu 2009-09-03 05:50:09

+0

不知道是否可以根據單選按鈕選擇設置會話變量並在此處讀取該值?應該有一個更簡單的方法!謝謝, Jim – James 2009-09-03 05:57:59

0

好吧,終於得到了這方面的工作多虧了大家的幫助。感謝JayRu指導我朝着正確的方向前進。這是我使用的(它仍然需要一些工作來掛鉤它):

HtmlForm form; 
     foreach (var ctl in Page.Controls[0].Controls) { 
      if (ctl is HtmlForm) { 
       form = ctl as HtmlForm; 
       ContentPlaceHolder holder = form.FindControl("DefaultContent") as ContentPlaceHolder; 
       if (holder != null) { 
        RadioButtonList rblControlHolder = holder.FindControl("rblActionLevel") as RadioButtonList; 
        if (rblControlHolder != null) { 
         if (rblControlHolder.SelectedValue == "Base") { 

         } 
        } 
       } 
      } 
     } 
+0

如果JayRu讓你找到解決方案的途徑,也許你應該接受他的答案。或者至少給他投票(假設你有足夠的代表投票...不知道) – 2009-09-03 13:32:09