Проблема с FindControl и динамически созданными элементами управления - PullRequest
4 голосов
/ 24 августа 2010

Пример кода:

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

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

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

Ответы [ 3 ]

5 голосов
/ 25 августа 2010

Насколько я могу судить, нет способа сделать то, что я пытаюсь выполнить, не добавив элемент управления на страницу. Если бы мне пришлось угадывать, я бы сказал, что 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;
    }
2 голосов
/ 24 августа 2010

Измените свой код на

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

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

0 голосов
/ 24 августа 2010

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

При отладке теста переменная lit равна нулю? Если это так, вам может потребоваться доступ к элементу по индексу элемента вместо использования метода FindControl ().

...