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

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

Добавление <%@ MasterType VirtualPath="~/MasterPage.master" %> не работает в UserControls.

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

Ответ 1

Нильс,

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

  • Создайте интерфейс, содержащий ваш метод.
  • Реализация интерфейса на главной странице
  • С вашего контроля ссылайтесь this.Page.Master на тип интерфейса.
  • Вызовите свой метод.

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

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

Ответ 2

Вы должны перенести this.Page.Master сначала как свойство Master страницы типа System.Web.UI.MasterPage.

например.

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

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

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

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

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

Ответ 3

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

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

Что именно вы хотите выполнить в своем контроле?

Ответ 4

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

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

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

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

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

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

/* 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 + the PageContoller позаботится об остальном.

Приветствия

Ответ 5

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

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

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

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

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

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

Затем в коде позади (С# в моем случае) у вас есть этот код:

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

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