2009-04-28 34 views
27

我在.NET 2.0/3.0之前的版本中使用過FindControl。現在看來,出於某種原因,我的控件的ID得到了一個名爲分配的時髦。例如,我將一個id「cbSelect」分配給一個複選框,但FindControl沒有找到它。當我查看HTML時,它被分配爲ctl00_bodyPlaceHolder_ctl02_cbSelectASP.Net FindControl不工作 - 怎麼回事?

我還沒有找到一個FindControl的例子提到。實際上,每個人似乎都只是使用像普通的查找控制。

那麼,我做錯了什麼? .Net是否改變?任何人都可以爲我闡明這一點,這真是令人沮喪!

回答

25

您可能正在使用MasterPage或用戶控件(ascx),這就是客戶端id更改的原因。想象一下,您在母版頁中使用與頁面中相同的ID進行控制。這會導致衝突。 id更改確保所有ClientID屬性在頁面上都是唯一的。

使用MasterPages時,FindControl需要特別注意。看看ASP.NET 2.0 MasterPages and FindControl()。 FindControl在naming container內工作。 MastePage和頁面是不同的命名容器。

+9

微軟實施這個的方式是這樣的一個笑話,它應該只是工作。哦,你有一個主頁?大約500個嵌套母版頁如何?該方法應該算出來,並且找到控制週期的必要條件。 – 2013-05-19 01:51:19

+0

你知道你在同一個想法中使用「應該」和「微軟」嗎? – user1566694 2016-12-13 20:32:28

1

當它呈現html時,ASP.NET會將所有控件ID與命名容器(用戶控件等)的ID作爲前綴一直回溯到文檔根目錄。這確保了所有ID對於後貼等都是唯一的。

這不影響使用FindControl,您應該在原始標記中使用ID。

8

我有運氣還算不錯解決此問題,工作中「最」的情況下用一個簡單的擴展方法

你可以在任何你認爲最好的高級容器控件上調用它,包括如果你想掃描整個控件層次結構的Page本身。

private static Control FindControlIterative(this Control control, string id) 
{ 
    Control ctl = control; 

    LinkedList<Control> controls = new LinkedList<Control>(); 

    while(ctl != null) 
    { 
    if(ctl.ID == id) 
    { 
     return ctl; 
    } 
    foreach(Control child in ctl.Controls) 
    { 
     if(child.ID == id) 
     { 
     return child; 
     } 
     if(child.HasControls()) 
     { 
     controls.AddLast(child); 
     } 
    } 
    ctl = controls.First.Value; 
    controls.Remove(ctl); 
    } 
    return null; 
} 
8

您可以使用遞歸來編寫擴展器以查找頁面上的任何控件。 這可能在某些Util/Helper類中。

public static Control FindAnyControl(this Page page, string controlId) 
    { 
     return FindControlRecursive(controlId, page.Form); 
    } 

    public static Control FindAnyControl(this UserControl control, string controlId) 
    { 
     return FindControlRecursive(controlId, control); 
    } 

    public static Control FindControlRecursive(string controlId, Control parent) 
    { 
     foreach (Control control in parent.Controls) 
     { 
      Control result = FindControlRecursive(controlId, control); 
      if (result != null) 
      { 
       return result; 
      } 
     } 
     return parent.FindControl(controlId); 
    } 
7

在控件集合中搜索控件時,請始終使用您分配給控件的標識,而不是在源標記呈現中看到的標識。如果FindControl()沒有找到你知道存在的控件,那麼很有可能你沒有在控件層次結構的右邊分支中搜索。遞歸函數對我來說是成功的。

這裏是我的就是我使用VB.NET 3.5例如:

Function FindControlRecursive(ByVal ctrl As Control, ByVal id As String) As Control 
    Dim c As Control = Nothing 

    If ctrl.ID = id Then 
     c = ctrl 
    Else 
     For Each childCtrl In ctrl.Controls 
      Dim resCtrl As Control = FindControlRecursive(childCtrl, id) 
      If resCtrl IsNot Nothing Then c = resCtrl 
     Next 
    End If 

    Return c 
End Function 

這裏是我怎麼會在局部我的基地頁類實現這個功能的例子:

Dim form HtmlForm = CType(FindControlRecursive(Me, "Form"), HtmlForm) 
+1

+1,因爲沒有看到你的我已經在C#中用相同的方法實現它: ``````````空值; if(ctl.ID == id)return ctl; (ctl.Controls.Count> 0) foreach(ctl.Controls中的Control sc) 控制fnd = FindControlRecursive(sc,id); if(fnd!= null)return fnd; } return null; }` – gkakas 2013-11-17 10:04:55

3

這是VB。NET代碼工作對我來說:

<Extension()> _ 
Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control 
    If controlToStartWith Is Nothing Then Return Nothing 
    If controlToStartWith.ID = controlIdToFind Then Return controlToStartWith 
    For Each childControl As Control In controlToStartWith.Controls 
     Dim resCtrl As Control = FindChildControlById(childControl, controlIdToFind) 
     If resCtrl IsNot Nothing Then Return resCtrl 
    Next childControl 
    Return Nothing 
End Function ' Function FindChildControlById(ByVal controlToStartWith As Control, ByVal controlIdToFind As String) As Control 

信用去喬治最初的VB.NET代碼。我只修改它少許,有2個功能改變:如果/當null /沒有任何東西作爲輸入控件傳遞時,我的錯誤不會發生錯誤,並且我的作爲擴展實現。我的其他3個較小的更改不影響功能,但對我來說,它們是代碼簡化。但我知道這很主觀。

那麼這種方法可以用於:

Dim c1 As Control = Page.FindChildControlById("aspControlID") 

如果你想將它轉換成一個特定的子類控制的,就像這樣:

Dim c1 As Control = Page.FindChildControlById("aspControlID") 
Dim c As HyperLink = TryCast(c1, HyperLink) 

更新:我的功能現在名爲'FindChildControlById'(以前是'FindMiControl')。我更喜歡SpeedNet的建議。