6

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

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

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

4

5 回答 5

12

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

例如

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

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

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

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

<!-- <%= MType %> //-->
于 2009-09-18T12:35:04.967 回答
7

尼尔斯,

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

  1. 创建一个包含您的方法的接口。
  2. 在母版页中实现接口
  3. 从您的控件中,this.Page.Master通过接口类型进行引用。
  4. 调用你的方法。

这是一种更好的 OO 方法,可以减少耦合,并且肯定会比运行时反射执行得更好。

我希望这有帮助!

于 2009-09-18T13:55:14.930 回答
4

如果您从用户控件中调用母版页上的函数,则您的代码非常紧密。

控件只能用于基于该母版的页面。我认为这通常是一个糟糕的设计,它至少会违反德米特法则。

你到底想在你的控制下完成什么?

于 2009-09-18T13:28:58.057 回答
1

JDunkerley 说得对。但是请允许我解释一下如何使用 MVP 将其解耦,这样您就可以努力避免 Heiko Hatzfeld 所说的设计问题。

基本上,为您的控件和母版页实现 MVP 模式。有关如何执行此操作的说明,请参见此处。在master的接口(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 会处理剩下的事情。

干杯

于 2009-09-18T15:42:38.367 回答
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";

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

于 2012-02-22T10:01:40.397 回答