2010-08-24 2 views
4

Пример кода:Проблемы с FindControl и динамически создаваемые элементы управления

var div = new HtmlGenericControl("div"); 
    div.Controls.Add(new Literal() { ID = "litSomeLit" }); 
    var lit = (Literal)div.FindControl("litSomeLit"); 
    Assert.IsNotNull(lit); 

Этот код не проходит утверждают, потому что горит равно нулю. Отладка показывает, что div.Controls определенно содержит литерал с идентификатором «litSomeLit». Мои вопросы: «Почему?» и «Есть ли способ получить контроль над конкретным идентификатором, не делая рекурсивного поиска div.Controls [] вручную по одному элементу за раз?»

Причина, по которой я делаю это, заключается в том, что мое фактическое приложение не так просто - метод, который я пишу, получает комплексное управление с несколькими субконтролями в ряде возможных конфигураций. Мне нужно получить доступ к определенному элементу управления несколькими слоями (например, элемент управления с идентификатором «txtSpecificControl» может быть равен StartingControl.Controls[0].Controls[2].Controls[1].Controls[3]). Обычно я мог бы просто делать FindControl("txtSpecificControl"), но это не работает, когда элементы управления были просто динамически созданы (как в приведенном выше примере кода).

ответ

4

Рядом, как я могу судить, нет способа сделать то, что я пытаюсь выполнить, не добавляя элемент управления на страницу. Если бы я должен был догадаться, я бы сказал, что FindControl использует свойство UniqueID элемента управления, которое обычно содержит идентификаторы всех элементов управления над текущим (например, OuterControlID $ LowerControlId $ TargetControlID). Это будет генерироваться только тогда, когда элемент управления фактически добавится на страницу.

Во всяком случае, вот реализация рекурсивной глубины первой-поиск FindControl, который будет работать, когда элемент управление не привязано к странице еще:

public static Control FindControl(Control parent, string id) 
    { 
     foreach (Control control in parent.Controls) 
     { 
      if (control.ID == id) 
      { 
       return control; 
      } 
      var childResult = FindControl(control, id); 
      if (childResult != null) 
      { 
       return childResult; 
      } 
     } 
     return null; 
    } 
+0

+1 Хорошая рекурсивная функция. Очень полезно – brenjt

0

Когда вы подтвердили, что элемент управления находится в коллекции Controls, вы сделали это, проверив коллекцию напрямую? FindControl() может не работать в этом контексте.

Когда вы отлаживаете тест, является var lit null? Если это так, вам может потребоваться доступ к элементу by by item вместо использования метода FindControl().

+0

A) Да, осматривая коллекцию Controls элемента управления. Тем не менее, следующий тест проходит просто отлично: http://snipt.net/fishtoaster/findcontrol/, что будет означать, что FindControl сможет его найти. B) Err, да. В этом весь вопрос - почему это нуль и/или как я могу обойти этот факт без необходимости проходить через и получить доступ ко всему по индексу элемента (что было бы утомительно, так как я точно не знаю, насколько глубоко и по какому индексу мой целевой контроль)? – Fishtoaster

2

Изменить код

var div = new HtmlGenericControl("div"); 
Page.Controls.Add(div); 
div.Controls.Add(new Literal() { ID = "litSomeLit" }); 
var lit = (Literal)div.FindControl("litSomeLit"); 

Насколько я знаю, FindControl работает только тогда, когда элемент управления находится в визуальном дереве страницы.

+0

Я не могу сделать это изменение, так как мой метод не знает, где элемент управления должен быть добавлен на страницу. Я мог бы добавить элемент управления на страницу, запустить FindControl, а затем удалить его со страницы, но это кажется даже хакерским, чем просто рекурсивный поиск вручную. – Fishtoaster

+0

Я не понимаю, вам нужно сделать findControl. так как вы создаете литеральную букву и держитесь за переменную до тех пор, пока не добавите ее на страницу, а затем снова воспользуетесь Page.FindControl, чтобы снова получить контроль. –

Смежные вопросы