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";
Без ссылки на главную страницу над вашим пользовательским элементом управления не сможет найти класс главной страницы.