6

Calling a function from the MasterPage in a Page is quite straigt forward but how do I call it for a UserControl:

Adding <%@ MasterType VirtualPath="~/MasterPage.master" %>, doesn't work on UserControls.

So this.Page.Master.MyFunction() fails :(

4

5 に答える 5

12

Page のMasterプロパティは System.Web.UI.MasterPage 型であるため、最初に this.Page.Master をキャストする必要があります。

例えば

((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 つのアプローチです。もう 1 つ考えられるのは、インターフェイスの実装です。

  1. メソッドを含むインターフェイスを作成します。
  2. マスター ページにインターフェイスを実装する
  3. コントロールからthis.Page.Master、インターフェイス タイプを介して参照します。
  4. メソッドを呼び出します。

これはより優れた OO アプローチであり、結合が少なくなり、ランタイム リフレクションよりも確実に優れたパフォーマンスを発揮します。

これが役立つことを願っています!

于 2009-09-18T13:55:14.930 に答える
4

ユーザーコントロール内からマスターページの関数を呼び出すと、コードが非常に複雑になります。

コントロールは、そのマスターに基づくページでのみ使用できます。これは通常悪い設計であり、少なくともデメテルの法則に違反すると思います。

あなたはあなたのコントロールで正確に何を達成したいですか?

于 2009-09-18T13:28:58.057 に答える
1

JDunkerleyはそれを正しく持っています。ただし、MVPを使用して分離する方法を説明し、HeikoHatzfeldが話している設計上の問題を回避できるようにします。

基本的に、コントロールとマスターページの両方にMVPパターンを実装します。その方法については、こちらをご覧ください。マスターのインターフェース(IMasterView)で呼び出すメソッドを宣言します。次に、2つのコンポーネント間の関係を制御するクラスを作成します。これを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+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 に答える