ASP.NET:通过UserControl在MasterPage中调用函数

时间:2009-09-18 12:20:36

标签: c# asp.net master-pages asp-usercontrols

从页面中的MasterPage调用函数非常简单,但如何为UserControl调用它:

添加<%@ MasterType VirtualPath="~/MasterPage.master" %>不适用于用户控件。

所以this.Page.Master.MyFunction()失败了:(

5 个答案:

答案 0 :(得分:12)

您必须首先强制转换this.Page.Master,因为Page的Master属性类型为System.Web.UI.MasterPage。

e.g。

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

您可以通过向用户控件后面的代码添加属性来检查基础母版页的类型:

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

并在用户控件标记中输出结果,例如添加此行以使其在源代码中作为注释打印出来:

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

答案 1 :(得分:7)

尼尔斯,

杠杆反射(由JDunkerley建议)是解决问题的一种方法。您可能考虑的另一个是实现一个接口:

  1. 创建包含方法的界面。
  2. 在母版页中实施界面
  3. 从您的控件中,通过界面类型引用this.Page.Master
  4. 打电话给你的方法。
  5. 这是一种更好的OO方法,可以减少耦合,并且肯定比运行时反射更好。

    我希望这有帮助!

答案 2 :(得分:4)

如果您在用户控件中调用母版页上的某个功能,那么您的代码非常大。

Control只能在基于该主控的页面上使用。我认为这通常是一个糟糕的设计,它至少会违反德米特定律。

你想在控制中完成什么?

答案 3 :(得分:1)

JDunkerley是对的。但请允许我解释如何使用MVP将其解耦,以便您可以努力避免Heiko Hatzfeld所讨论的设计问题。

基本上,为控件和母版页实现MVP模式。有关如何执行此操作的说明,请参阅here。在主接口(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();
}

确保在控件的界面(IControlView)中声明“EventFired”事件并在控件中实现。然后你要做的就是影响master(调用它的方法),触发这个事件,MVP + PageContoller将处理剩下的事情。

干杯

答案 4 :(得分:1)

我无法得到上述工作的答案,所以这对我有用:

您想要从用户控件引用母版页属性。

首先,您的母版页将具有如下公共属性:

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";

如果没有上面的母版页,您的用户控件将无法找到母版页类。