ASP.NET: вызов функции в MasterPage через UserControl

вызов функции из MasterPage на странице довольно прямой, но как я могу вызвать ее для UserControl:

добавлять <%@ MasterType VirtualPath="~/MasterPage.master" %>, не работает на UserControls.

Так this.Page.Master.MyFunction() не удается :(

5 ответов


Нильс,

отражение рычагов (как предложил JDunkerley) - это один из подходов к проблеме. Еще можно рассмотреть реализует интерфейс:

  1. создайте интерфейс, который включает ваш метод.
  2. реализует интерфейс на главной странице
  3. из вашего управления, ссылка this.Page.Master по типу интерфейса.
  4. вызов ваш метод.

Это лучший подход ОО, водит к меньше соединения, и, безусловно, будет работать лучше, чем runtime reflection.

надеюсь, это поможет!


вы должны бросить это.Страница.Мастер сначала как мастер свойство страницы имеет тип System.Сеть.ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС.мастер-страница.

например

((MyMaster)this.Page.Master).MyFunction();

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

    public string MType
    {
        get { return this.Page.Master.GetType().FullName; }
    }

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

<!-- <%= MType %> //-->

вы очень сильно переворачиваете свой код, если вы вызываете функцию на masterpage из своего пользовательского элемента управления.

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

чего именно вы хотите достичь в своем контроле?


JDunkerley имеет это право. Но позвольте мне объяснить, как отделить его с помощью MVP, чтобы вы могли работать над тем, чтобы избежать проблемы дизайна, о которой говорит Хейко Хацифельд.

В основном, реализуйте шаблон MVP как для вашего элемента управления, так и для главной страницы. См.здесь Инструкции о том, как это сделать. Объявите метод, который вы хотите вызвать в главном интерфейсе (IMasterView). Затем создайте класс, который будет контролировать отношения между двумя компонентами; мы будем назовите его классом PageController. Поместите экземпляр этого класса в состояние запроса для каждого запроса, добавив следующую строку в global.асакс.cs:

/* global.asax.cs */
protected void Application_BeginRequest(object sender, EventArgs e)
{
    // ...
    HttpContext.Current.Items["Controller"] = new PageController();
    // ...
}

вы можете получить доступ к этому экземпляру от каждого из ведущих (master и control) через следующую строку кода:

var controller = HttpContext.Current.Items["Controller"] as PageController;

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

/* PageController.cs */
public event EventHandler SomeEvent;

protected virtual void OnSomeEvent(EventArgs e)
{
    Debug.Assert(null != e);

    var handler = this.SomeEvent;
    if (null != handler)
        handler(this, e);
}

public void FireSomeEvent()
{
   this.OnSomeEvent(EventArgs.Empty);
}

/* ControlPresenter.cs */
public ControlPresenter(IControlView view)
    : base()
{
    view.EventFired += (sender, e) =>
    {
        var controller = HttpContext.Current.Items["Controller"] as PageController;
        controller.FireSomeEvent();
    };
}

/* MasterPresenter.cs */
public MasterPresenter (IMasterView view)
    : base()
{
    var controller = HttpContext.Current.Items["Controller"] as PageController;
    controller.SomeEvent += (sender, e) => view.MyFunction();
}

убедитесь, что событие "EventFired" объявлено в интерфейсе элемента управления (IControlView) и реализовано в элементе управления. Тогда все, что вам нужно сделать, чтобы повлиять на мастера (вызвать его метод), это запустить это событие, а MVP + PageContoller позаботится об остальном.

Ура


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

вы хотите ссылаться на свойство главной страницы из пользовательского элемента управления.

во-первых, ваша главная страница будет иметь общественную собственность, как так :

public string BodyClass
{
    set
    {
        this.masterBody.Attributes.Add("class", value);
    }
}

Теперь добавьте ссылку на главную страницу в файле ASCX пользовательского элемента управления следующим образом:

<%@ Register Src="~/Source/MasterPages/Main.master" TagPrefix="MSTR" TagName="MasterPage" %>

потом в коде (C# в моем случае) у вас есть этот код :

Main masterPage = (Main)this.Page.Master;
masterPage.BodyClass = "container";

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