Вложенные пользовательские элементы управления - как лучше получить ссылку на элемент управления предка - PullRequest
1 голос
/ 15 января 2009

Я понимаю, что большой объем кода здесь не помещается, но я прошу общее направление или указатель.

У меня есть пользовательские элементы управления .NET, вложенные в шесть глубин для интерактивного гаджета с (внешняя или внутренняя) из: оболочки, вкладок, панелей, списков, строк, элементов.

Я пытаюсь получить ссылку на элемент управления предка из вложенного элемента управления.

В частности, у меня есть этот код в коде встроенного элемента управления "great great grand child". Это работает, но это очень некрасиво:

MyTab _myTab = this.Parent.Parent.Parent.Parent.FindControl(thisTab) as MyTab;

, что равно {ASP.controls_appname_widget_mywidget_mytab_ascx} и является правильным.

Я понимаю, что могу сделать что-то вроде Page.FindControl ("MyWrapper: MyPanel: etc .....), но это также не рекомендуется, так как структура или идентификаторы могут изменяться ....

Есть ли достойная альтернатива?

Ответы [ 5 ]

2 голосов
/ 15 января 2009

Помните, что компоненты лучше всего не знать. Вы никогда не хотите, чтобы у какого-либо элемента управления было что-либо, находящееся выше в иерархии, и что у него есть только интерфейсное знание элементов управления, находящихся ниже в иерархии. Этот архитектурный подход избавит вас от боли и страданий в долгосрочной перспективе и позволит избежать ситуаций, в которых вы находитесь сейчас.

Что касается исправления текущей проблемы, лучший способ ее исправить - создать элемент MyTab в вашем элементе управления, который устанавливается родительскими элементами управления. Это не идеальное решение, поскольку ваш контроль не совсем неосведомлен с другими, но, по крайней мере, вам больше не нужно будет знать, как получить справку MyTab - она ​​будет предоставлена ​​вам.

Таким образом, я бы создал свойство, называемое чем-то вроде ParentTab, и установил бы это свойство равным ссылке MyTab где-нибудь на странице или внутри элемента управления, который имеет и должен иметь видимость как для MyTab, так и для вашего элемента управления.

0 голосов
/ 04 декабря 2010
public static class Extension{
 public static Control FindControlRecursive(this Control control, string idToFind)
 {
     Control result;
     if(control != null){
        result = control.FindControl(idToFind);
     }
     if(result != null){ return result; }
     if(result == null && control.Parent != null){
         return control.Parent.FindRecursive(idToFind);
     }
     return null;
  }
}
0 голосов
/ 15 января 2009

@ Эндрю, не для того, чтобы угнать мою собственную ветку, а просто для того, чтобы уточнить и обсудить подход к проектированию. Вы сказали: «Вы никогда не хотите, чтобы какой-либо элемент управления знал что-либо выше себя в иерархии ...». Это отличная стратегия проектирования по очевидным причинам. Но как насчет контейнера-обертки со встроенным централизованным управлением? Например, в .NET - элемент управления ScriptManager на вложенной главной странице. Вы бы хотели, чтобы менеджер скриптов создавался только один раз, и вы хотели бы, чтобы он был доступен для различных элементов управления в приложении. Например, любой элемент UpdatePanel в любом встроенном элементе управления в приложении хотел бы знать о существовании этого ScriptManager. Это неправильный подход?

Мой дизайн аналогичен - внешний контейнер-обертка управляет сохранением объекта, и каждый элемент управления может сохранять свое состояние в этом диспетчере. Я думаю, что делегаты-обертки - лучший дизайн для этого. Потому что мне не нравится Parent.Parent. и т. д. или обход контрольных идентификаторов только для ссылки. Любые комментарии приветствуются.

0 голосов
/ 15 января 2009

Я думаю, это действительно зависит от того, как вы используете элементы управления. Если элемент управления обслуживает только одну бизнес-задачу и используется только на одной странице для удовлетворения сценария использования, тогда не нужно сходить с ума от интерфейсов и свойств. Я не вижу ничего плохого в идее parent.parent.parent.etc; использовал это много раз сам. Я хотел бы заключить его в свойство, чтобы всякий раз, когда вам это нужно, вы могли вызывать this.MyGreatGreatGrandFatherProperty. Это будет более читабельным, и если ваша глубина иерархии изменится, вам нужно будет исправить только одно место.

Теперь, если это универсальный компонент, которым вы не управляете использованием, или он понадобится во многих случаях использования, вам нужно добавить свойства для родителей, чтобы сообщить вам, кто они должны быть разорваны.

0 голосов
/ 15 января 2009

Привет, вы могли бы использовать селектор WebControl, который на самом деле является независимым проектом (лицензия == LGPL), но все еще является частью основного Ra-Ajax download ...

Проверьте код и пример использования здесь ...

Тогда вы можете просто выполнить поиск по объекту Page, и он будет рекурсивно искать элемент управления, соответствующий вашим (любым) критериям в делегате ...

...