Инициализация дочернего элемента управления в пользовательской композиции в ASP.NET - PullRequest
3 голосов
/ 24 сентября 2008

Часть серии элементов управления, над которыми я работаю, очевидно, включает в себя объединение некоторых из них в композиты. Я быстро начинаю понимать, что это необходимо учитывать (это все для меня ново!):)

У меня в основном есть StyledWindow элемент управления, который по сути является прославленным Panel с возможностью делать другие биты (например, добавлять границы и т. Д.).

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

    protected override void CreateChildControls()
    {
        _panel = new Panel();

        if (_editable != null)
            _editable.InstantiateIn(_panel);

        _regions = new List<IAttributeAccessor>();
        _regions.Add(_panel);
    }

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

Теперь это приводило к ошибкам "объект ноль", но я локализовал это до метода рендеринга, который, конечно, пытался вызвать метод для объекта [нуль] Page.

Что меня смущает, так это то, что элемент управления отлично работает как автономный, но при установке в StyledWindow все идет ужасно неправильно!

Итак, похоже, я что-то упустил в своих StyledWindow или ChildControl. Есть идеи?

Обновление

Как правильно заметил Брэд Уилсон , вы не видите элементы управления, добавляемые в коллекцию Controls. Это то, для чего _panel, это было для меня, в основном тогда переопределить Controls (я получил это от гида где-то):

    Panel _panel;    // Sub-Control to store the "Content".
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _panel.Controls;
        }
    }

Надеюсь, это поможет прояснить ситуацию. Извинения.

Обновление после Ответ Longhorn213

Правильно, я немного поиграл с элементом управления, поместив один в композит, а другой снаружи. Затем я получил статус Page на главном событии события в жизненном цикле элемента управления и отобразил его на странице.

Автономный сервер работает нормально, и страница запускается, как и ожидалось. Однако тот, который вложен в Composite, отличается. Это событие OnLoad вообще не запускается! Поэтому я предполагаю, что Брэд, вероятно, прав в том, что я неправильно настраиваю иерархию управления. Может ли кто-нибудь дать совет относительно того, чего мне не хватает? Метод Панели не достаточно? (ну, это явно не так ?!): D

Спасибо за вашу помощь, ребята, оценили:)

Ответы [ 4 ]

2 голосов
/ 24 сентября 2008

Я не вижу, чтобы вы добавляли свои элементы управления в коллекцию элементов управления, что объясняет, почему они не могут получить доступ к странице (поскольку они никогда официально не размещались на странице).

1 голос
/ 25 сентября 2008

Решено!

Правильно, я был полон решимости получить этот взлом сегодня! Вот мои мысли:

  • Я думал, что использование Panel было чем-то вроде хака, поэтому я должен удалить его и выяснить, как это действительно делается.
  • Я не хотел делать что-то вроде MyCtl.Controls[0].Controls для доступа к элементам управления, добавленным в композит.
  • Я хотел, чтобы эта чертова штука работала!

Итак, я начал поиск и нажал MSDN , этот artcle был ДЕЙСТВИТЕЛЬНО полезен (то есть почти как копия 'n' вставил и хорошо объяснил - что-то MSDN традиционно плох). Nice!

Итак, я разорвал использование Panel и в значительной степени последовал за artcle и принял его как евангелие, делая заметки, как я пошел.

Вот что у меня сейчас:

  • Я узнал, что использовал неправильный термин. Я должен был назвать это Templated Control . В то время как шаблонные элементы управления являются технически составными, есть четкое различие. Шаблонные элементы управления могут определять интерфейс для элементов, которые к ним добавляются.
  • Шаблонные элементы управления очень мощные и на самом деле довольно быстрые и простые в настройке, как только вы осознаете их!
  • Я еще поиграю с поддержкой дизайнера, чтобы убедиться, что я все понимаю, а затем получу сообщение в блоге:)
  • Элемент управления «Шаблон» используется для указания интерфейса для шаблонных данных.

Например, вот разметка ASPX для шаблонного элемента управления:

<cc1:TemplatedControl ID="MyCtl" runat="server">
    <Template>
        <!-- Templated Content Goes Here -->
    </Template>
</cc1:TemplatedControl>   

Вот код, который у меня есть сейчас

public class DummyWebControl : WebControl
{
    // Acts as the surrogate for the templated controls.
    // This is essentially the "interface" for the templated data.
}

В TemplateControl.cs ...

    ITemplate _template;
    // Surrogate to hold the controls instantiated from 
    // within the template.
    DummyWebControl _owner;

    protected override void CreateChildControls()
    {
        // Note we are calling base.Controls here
        // (you will see why in a min).
        base.Controls.Clear();
        _owner = new DummyWebControl();

        // Load the Template Content
        ITemplate template = _template;
        if (template == null)
            template = new StyledWindowDefaultTemplate();
        template.InstantiateIn(_owner);

        base.Controls.Add(_owner);
        ChildControlsCreated = true;
    }

Затем, чтобы обеспечить легкий доступ к элементам управления [Суррогатного] объекта:

(именно поэтому нам нужно было очистить / добавить базу. Контроль)

    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _owner.Controls;
        }
    }

И это все, легко, когда ты умеешь! :)

Далее: Поддержка области времени проектирования!

1 голос
/ 24 сентября 2008

Я всегда помещал вызовы JavaScript в функцию OnLoad. Такие как ниже.

protected override void OnLoad(EventArgs e)
{

    // Do something to get the script
    string script = GetScript();

    this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "SomeJavaScriptName", script);

    // Could also use this function to determine if the script has been register. i.e. more than 1 of the controls exists
    this.Page.ClientScript.IsClientScriptBlockRegistered("SomeJavaScriptName");

    base.OnLoad(e);
}

Если вы все еще хотите выполнить рендеринг, вы можете просто написать скрипт в ответе. Именно это и делает RegisterScriptBlock, он просто помещает скрипт на страницу.

0 голосов
/ 25 сентября 2008

Правильно, я начал играть и понял, что что-то не так с моим экземпляром управления, поскольку Longhorn был прав, я должен иметь возможность создавать ссылки на сценарии в OnLoad (а я не мог), а Брэд был прав в этом я должен убедиться, что моя иерархия Controls была поддержана путем добавления в коллекцию Controls составного.

Итак, у меня было две вещи:

  1. Я переопределил средство доступа к свойству Controls для композита, чтобы вернуть эту коллекцию Controls Panel, так как я не хочу идти ctl.Controls[0].Controls[0], чтобы получить нужный элемент управления. Я удалил это, но мне нужно отсортировать это.
  2. Я не добавил Panel в коллекцию Controls, Я уже сделал это.

Итак, теперь он работает, однако, как мне получить свойство Controls для составного элемента, возвращающее элементы в Panel, а не сам Panel?

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