none
Динамическая загрузка кастом контрола, содержащего другие контролы, asp.net RRS feed

  • Вопрос

  • Здравствуйте,

     

    Задача вот в чем, есть контрол, который находиться в отдельной библиотеке. В нем лежит Grid + вызов других контролов.

    Как я ее реализовываю, подымаю на рантайме, отдельную библиотеку, получаю тип контрола через  GetType, даю тип библиотеки на вход методу LoadControl, и пытаюсь добавить ее в колекцию placeholder'а. Но контрол не добавляется, хотя и ошибок не каких не выдается. Проверил по шагам, библиотека подгружается нормально, тип получается нормально, но отображения все равно нет.

    В чем может быть проблема?

            Assembly a = Assembly.LoadFile(@"D:\ClassLibrary1.dll");
            var type= a.GetType("WebUserControl");

            var ctrl = LoadControl(type, null);
            placeHolder.Controls.Add(ctrl);

    ps в ClassLibrary контрол я добавил через Add existing element.

    Буду рад советам.

     

    3 февраля 2012 г. 16:40

Ответы

  • Насколько я понял, вы просто скопировали в ClassLibrary1.dll User-control из сайта - три файла: ascx, cs и designer.cs. Такой вариант не заработает.

    Asp.net обрабатывает контролы, лежащие в сайте, примерно так:

    1. При сохранении asсx студия парсит его, и вписывает в designer.cs объявления всех вложенных контролов. Код из инициализации не генерируется

    2. При компиляции приложения (web application или class library) в dll файл попадает код из cs и designer.cs. Кода инициализации контролов в выходном файле dll нет.

    3. уже во время работы приложения, при отображении контрола на странице - при открытии страницы с контролом, или при добавлении контрола вызовом Page.LoadControl(string), asp.net (не студия, и не компилятор при сборке) генерирует класс-наследник от вашего WebUserControl1, и вписывает в его OnInit код инициализации вложенных контролов. В Render сгенерированного класса вписывается код редеринга разметки из ascx-файла.

    В вашем случае ascx-файл просто пропадает. Именно поэтому при добавлении New Item в Class Library есть шаблон Web Custom Control, но нет шаблона Web User Control.

    Два варианта - попробовать все-таки вшить контрол в class library (http://stackoverflow.com/questions/1765867/asp-net-usercontrol-class-library). Или перейти на Web Custom Control-ы, и работать с разметкой в ручную. Или перейти на mvc, в нем логика представления (код контроллера) не привязана к разметке View.

    24 февраля 2012 г. 15:53

Все ответы

  • > и пытаюсь добавить ее в колекцию placeholder'а

    На каком этапе, в Page_Init?

    8 февраля 2012 г. 6:48
  • А размеры в конструкторе по умолчания для контрола устанавливаются? Может просто у него ширина и высота равны 0, поэтому его не видно. Т.к. вызывая LoadControl со вторым параметром null - вы создаете контрол с помощью конструктора по умолчанию.


    Для связи [mail]

    8 февраля 2012 г. 8:08
    Модератор
  • пробывал и в page_init и в page_load и в pre_render
    9 февраля 2012 г. 6:41
  • Добавил в контрол свойства Width и Heigth, который устанавливали значения для внутренниего серверного контрола (в примере обычный лэйбл), но при установки значения свальвается ошибка, так как на тот момент контрол еще не создан (вызвал в Page_Load):

    protected void Page_Load(object sender, EventArgs e)
        {
            Assembly a = Assembly.LoadFile(@"D:\ClassLibrary1.dll");
            var type= a.GetType("WebUserControl");
            var ctrl = LoadControl(type, null);
            ctrl.Width = 10;
            ctrl.Heigth = 10;
            placeHolder.Controls.Add(ctrl);
        }

    у меня такое ощущение, что вся проблема в том, что не вызывается метод инициализации контролов, при таком способе, те контрол добовляется (метод FindControl его находит), но его значение null ...

    9 февраля 2012 г. 6:46
  • вопрос все еще открыт
    12 февраля 2012 г. 13:47
  • Page_Load - поздно. Надо в Page_Init
    13 февраля 2012 г. 9:53
  • в page_init тоже пробывал
    14 февраля 2012 г. 16:43
  • А в какой момент вы инициализируете внутренние контролы? Стандартный способ установки значений должен создать контролы, если они еще не созданы, по цепочке:

    • WebUserControl.Width ищет лэйбл через this.FindControl("someLabel")
    • this.FindControl вызывает EnsureChildControls
    • EnsureChildControls вызывает CreateChildControls
    • в CreateChildControls вы создаете someLabel

    Можете показать код самого контрола?

    14 февраля 2012 г. 17:01
  • Извиняюсь, что долго не отвечалЮ был другой проект.

    я не доконца понял что вы имели ввиду, как я понял, вы описали механизм инициализации внутренних контролов при вызове LoadControl, если так то они не отрабатывают, может правда я не правильно вас понял.

    Сам код очень простой:

    В контроле есть кнопка btn (для примера), я сделал я чтобы свойства высоты и ширины для него были свойствами основного контрола :

       namespace WebApplication3
    {
        public partial class WebUserControl1 : System.Web.UI.UserControl
        {
            public double Width
            {
                get
                {
                    return bbb.Width.Value;
                }
                set
                {
                    bbb.Width = new Unit(value);
                }
            }

            public double Height
            {
                get
                {
                    return bbb.Height.Value;
                }
                set
                {
                    bbb.Height = new Unit(value);
                }
            }

            protected void Page_Load(object sender, EventArgs e)
            {

            }
        }
    }

    Вызов контрола на строничке, я пример упростил :

    namespace WebApplication3 { public partial class _Default : System.Web.UI.Page { protected override void OnPreInit(EventArgs e) { base.OnPreInit(e); } protected override void OnInit(EventArgs e) { base.OnInit(e); var cntrl = (WebUserControl1)LoadControl(typeof(WebUserControl1), null);

    cntrl.ID = "cntrl";

    cntrl.Visible = true; cntrl.Width = 10; cntrl.Height = 10; Page.Controls.Add(cntrl); } protected void Page_Load(object sender, EventArgs e) { } } }

    свойства Width и Height  -  бросают ошибку, так как внутренние конролы не инициализированы. Если убрать установку этих свойст, то FindControl находит cntrl на странице.

    Буду благодарен, за помощь.

    19 февраля 2012 г. 18:59
  • Насколько я понял, вы просто скопировали в ClassLibrary1.dll User-control из сайта - три файла: ascx, cs и designer.cs. Такой вариант не заработает.

    Asp.net обрабатывает контролы, лежащие в сайте, примерно так:

    1. При сохранении asсx студия парсит его, и вписывает в designer.cs объявления всех вложенных контролов. Код из инициализации не генерируется

    2. При компиляции приложения (web application или class library) в dll файл попадает код из cs и designer.cs. Кода инициализации контролов в выходном файле dll нет.

    3. уже во время работы приложения, при отображении контрола на странице - при открытии страницы с контролом, или при добавлении контрола вызовом Page.LoadControl(string), asp.net (не студия, и не компилятор при сборке) генерирует класс-наследник от вашего WebUserControl1, и вписывает в его OnInit код инициализации вложенных контролов. В Render сгенерированного класса вписывается код редеринга разметки из ascx-файла.

    В вашем случае ascx-файл просто пропадает. Именно поэтому при добавлении New Item в Class Library есть шаблон Web Custom Control, но нет шаблона Web User Control.

    Два варианта - попробовать все-таки вшить контрол в class library (http://stackoverflow.com/questions/1765867/asp-net-usercontrol-class-library). Или перейти на Web Custom Control-ы, и работать с разметкой в ручную. Или перейти на mvc, в нем логика представления (код контроллера) не привязана к разметке View.

    24 февраля 2012 г. 15:53