zoukankan      html  css  js  c++  java
  • Passing Information Between Content and Master Pages .

    Introduction
    When graphic designers create a layout for a Web site, they typically break down page layout into distinct regions, such as a common header that includes the logo and various navigation links, a left

    perhaps, the main content area, and perhaps some sort of site map or legalese at the footer of the page. ASP.NET 2.0 makes defining these regions and applying them to multiple pages across a website a breeze with Master Pages. A Master Page allows a page developer to define a site-wide layout, marking what regions are customizable on a page-by-page basis. For more on using Master Pages and their advantages, see A Sneak Peak at MasterPages in ASP.NET 2.0.

    One common challenge that faces page developers using Master Pages is how to pass information from a Master Page to its content page, or vice-a-versa. A Master Page might contain a DropDownList control that when its selected index changes, the corresponding content page needs to have its display updated. Or perhaps some action in the content page needs to update the appearance of the Master Page. In this article we will explore techniques for passing information between a Master Page and its content page. Read on to learn more!  

    Master Page and Content Page Design Basics
    As a website grows, new content pages will no doubt be added and associated with existing Master Pages. Or existing content pages that use MasterPage X might be updated to use Master Page Y instead. Consequently, it's smart to design your Master Pages so that there is no reliance on their content pages. That is, a Master Page shouldn't assume that its content page possesses a particular method or that it has a specific set of Web controls defined in its declarative markup. Such a Master Page is said to be loosely-coupled with its content page; if the Master Page expects particular methods or Web controls on its corresponding contnet pages, then it's said to be tightly-coupled.

    It's possible for a Master Page to be loosely-coupled to its content page, but for the content page to be tightly-coupled to the Master Page. For example, the Master Page may make no assumptions and not base any functionality on its content page's methods or markup, but the page may assume that the Master Page has a particular method or Web control present. Ideally, a page will be loosely-coupled with its Master Page, but if information needs to be passed between a Master Page and its content page (or vice-a-versa), there must be some level of coupling, either from the Master Page to the content page (bad) or the content page to the Master Page (better). The demos in this article establish a tight-coupling from the content pages to their Master Pages, but retain a loose-coupling from the Master Pages to their content pages.

    Why the Tight-Coupling From the Content Page to Master Page is Preferred
    You may be wondering why I recommend a coupling from the content page to the Master Page rather than the other way around. When there exists a coupling from A to B, modifying B typically requires a corresponding modification to A. Since I expect that most websites have far fewer Master Pages than content pages, and that Master Pages are less likely to have their tightly-coupled interface modified than in a content page, from a logistics standpoint it makes sense to introduce the coupling from content pages to Master Pages. Secondarily, this coupling direction just feels "better". When associating a new web page with an existing Master Page, it seems funky to have to stop and think, "OK, now what functionality does this page need to expose in order to work with this Master Page?" If this is a triffle confusing, don't sweat it. I think once you explore the demos the coupling issue will make more sense.

    Passing Information from a Content Page to its Master Page
    A Master Page can expose its Web controls or methods directly to its content pages. To expose a method, simply mark it as public from the Master Page's code-behind class:

    ' VB...
    Partial Class MasterPageFiles_Main
       Inherits System.Web.UI.MasterPage

       Public Sub DisplayDataFromPage(ByVal message As String)
          DataFromPage.Text = message
       End Sub

    End Class


    // C#
    public partial class MasterPageFiles_MainCS : System.Web.UI.MasterPage
    {
       public void DisplayDataFromPage(string message)
       {
          DataFromPage.Text = message;
       }

    }

    Here DataFromPage is a Label Web control in the Master Page's declarative markup. The method DisplayDataFromPage is a public method that can be invoked from the Master Page's content page. The string input passed into this method is assigned to the Label Web control's Text property. Using this method, the Master Page's content page can set the text displayed in the DataFromPage Label.

    Additionally, the Master Page can expose a Web control from its declarative syntax as a read-only property:

    ' VB...
    Partial Class MasterPageFiles_Main
       Inherits System.Web.UI.MasterPage

       Public ReadOnly Property DataFromPageLabelControl() As Label
          Get
             Return Me.DataFromPage
          End Get
       End Property

    End Class


    // C#
    public partial class MasterPageFiles_MainCS : System.Web.UI.MasterPage
    {
       public Label DataFromPageLabelControl
       {
          get
          {
             return this.DataFromPage;
          }
       }

    }

    To access the Master Page's methods or properties from a content page, reference the Master Page through the Page.Master property. This property returns an object of type MasterPage, so you'll need to explicitly cast it to the appropriate type before calling its methods or referencing its properties. Alternatively, you can set the @MasterType directive, which adds a property to the auto-generated ASP.NET code-behind class code named Master that is a strongly-typed reference to the specified Master Page.

    The following markup in the .aspx file for the content page spells out the Master Page type:

    <%@ MasterType VirtualPath="pathToMasterPage" %>

    With this directive added (and the .aspx file saved), you can reference the Master Page's public methods and properties programmatically in the content page's code-behind class using Master like so:

    ' VB...
    Partial Class Demos_PassInfoToMasterPage
       Inherits System.Web.UI.Page

       Protected Sub ShowText_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ShowText.Click
          'Call the Main.master Master Page's DisplayDataFromPage method
          Master.DisplayDataFromPage(TextToShowInMasterPage.Text)

          ' OPTIONAL: Could reference the control directly through the Master Page's DataFromPageLabelControl property
          ' Master.DataFromPageLabelControl.Text = TextToShowInMasterPage.Text
       End Sub
    End Class

    // C#
    public partial class Demos_PassInfoToMasterPageCS : System.Web.UI.Page
    {
       protected void ShowText_Click(object sender, EventArgs e)
       {
          // Call the Main.master Master Page's DisplayDataFromPage method
          Master.DisplayDataFromPage(TextToShowInMasterPage.Text);

          // OPTIONAL: Could reference the control directly through the Master Page's DataFromPageLabelControl property
          // Master.DataFromPageLabelControl.Text = TextToShowInMasterPage.Text;
       }
    }

    The code shown here, which is available from the download at the end of this article, is from a content page that includes a TextBox named TextToShowInMasterPage and a Button Web control named ShowText. When the ShowText Button is clicked, the Master Page's DisplayDataFromPage method is called, passed the value of the TextBox's Text property. (Alternatively, the Master Page's DataFromPageLabelControl property could be used to reference the Label control in the Master Page, at which point its Text property could be set.) The net result is that entering text into the TextBox on the content page and clicking the Button results in the Master Page's display updating to display this user-entered text.

    The Master Page is updated by the text entered in the content page.

    Page.Master versus Master
    If you use the @MasterType directive to create a strongly-typed Master Page reference in the content page's code-behind class, you must use Master to get a strongly-typed reference. If your code uses Page.Master, you'll get a loosely-typed reference (one whose type is MasterPage and, therefore, requires a cast before the specific Master Page's members can be accessed).

    Passing Information from a Master Page to its Content Page
    In certain scenarios a Master Page might contain a Web control that, when modified by a user in some fashion, needs to update the corresponding content page. Perhaps the Master Page contains a DropDownList control that, when modified, needs to refresh the page and display data based on the selected item. Personally, I think such functionality should be moved to a separate User Control and that User Control added to the ASP.NET content pages, as needed. However, you may have a situation in which it is imperative that the Master Page pass information to a content page, so it's worth exploring techniques for accomplishing this.

    As aforementioned, I'd strongly encourage you to not establish a tight-coupling from the Master Page to the content page. Such a tight-coupling can be avoided by having the Master Page not directly call some content page method, but instead through the judicious use of events. In short, we can create a Master Page that raises an event when some action happens on the Master Page side. This event can pass any additional information needed and then content pages that require this information can "subscribe" to the Master Page's event. (An alternate approach, not explored in this article, is to have the content page assign a delegate to a property in the Master Page. This technique is discussed in Tim Stall's article, Trigger Page Methods from a User Control. While Tim's article deals with User Controls and ASP.NET pages, the concepts apply equally to Master Pages (the User Control) and content pages (the ASP.NET page).)

    To illustrate this, imagine that we had a DropDownList in the Master Page. When its selected index changes, we want to notify the content page of the change so that it can update its display accordingly. Start by creating a DropDownList named Moods in the Master Page that lists various moods (Happy, Sad, etc.) and then create an event handler for this DropDownList's SelectedIndexChanged event. Next, we need to define an event for the Master Page, specifying the event handler signature. The event handler signature specifies what input parameters are passed to the event handler. For this example, let's pass the selected DropDownList item's Text and Value property values. Therefore, we can use the CommandEventHandler delegate, which passes a CommandEventArgs object to the event handler, which includes CommandName and CommandArgument properties that we can use to hold the selected ListItem's Text and Value property values.

    To define an event named MoodChanged for the Master Page that uses the CommandEventHandler delegate, use the following syntax:

    ' VB...
    Partial Class MasterPageFiles_Main
       Inherits System.Web.UI.MasterPage

       Public Event MoodChanged As CommandEventHandler
    End Class

    // C#
    public partial class MasterPageFiles_MainCS : System.Web.UI.MasterPage
    {
       public event CommandEventHandler MoodChanged;
    }

    When the DropDownList's SelectedIndexChanged event fires we want to raise the Master Page's MoodChanged event. To accomplish this, add the following code into the DropDownList's SelectedIndexChanged event handler:

    ' VB...
    Partial Class MasterPageFiles_Main
       Inherits System.Web.UI.MasterPage

       Public Event MoodChanged As CommandEventHandler

       Protected Sub Moods_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Moods.SelectedIndexChanged
          If Moods.SelectedIndex <> 0 Then
             RaiseEvent MoodChanged(Me, New CommandEventArgs(Moods.SelectedItem.Text, Moods.SelectedValue))
          End If
       End Sub

    End Class

    // C#
    public partial class MasterPageFiles_MainCS : System.Web.UI.MasterPage
    {
       public event CommandEventHandler MoodChanged;

       protected void Moods_SelectedIndexChanged(object sender, EventArgs e)
       {
          if (Moods.SelectedIndex != 0 && MoodChanged != null)
             MoodChanged(this, new CommandEventArgs(Moods.SelectedItem.Text, Moods.SelectedValue));
       }

    }

    Note: In C#, we have to first check that the event is not null before raising it (note the "&& MoodChanged != null" check in the if statement). This is because the event reference is null if no one has subscribed to the event...

    The last step is "subscribing" to the event in the content page's that care about the changing of this DropDownList. To subscribe to the event we need to programmatically specify in the content page that when the Master Page's MoodChanged event fires that a particular event handler defined in the content page should execute. The following code illustrates how to establish this binding between the event and the event handler in C# and VB:

    ' VB...
    Partial Class Demos_PassInfoToPage
       Inherits System.Web.UI.Page

       Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
          'Wire up the event (MoodChanged) to the event handler (MoodChangedFromMasterPage)
          AddHandler Master.MoodChanged, AddressOf MoodChangedFromMasterPage
       End Sub

       Private Sub MoodChangedFromMasterPage(ByVal sender As Object, ByVal e As CommandEventArgs)
          Dim moodText As String = e.CommandName
          Dim moodValue As String = e.CommandArgument.ToString

          MoodChangedLabel.Text = String.Format("You have selected mood {0}, which has a value of {1}...", moodText, moodValue)
       End Sub

    End Class

    // C#
    public partial class Demos_PassInfoToPageCS : System.Web.UI.Page
    {
       protected void Page_Init(object sender, EventArgs e)
       {
          // Wire up the event (MoodChanged) to the event handler (MoodChangedFromMasterPage)
          Master.MoodChanged += new CommandEventHandler(MoodChangedFromMasterPage);
       }

       private void MoodChangedFromMasterPage(object sender, CommandEventArgs e)
       {
          string moodText = e.CommandName;
          string moodValue = e.CommandArgument.ToString();

          MoodChangedLabel.Text = String.Format("You have selected mood {0}, which has a value of {1}...", moodText, moodValue);
    }
    }

    The Page_Init event handler associates the Master Page's MoodChanged event with the event handler MoodChangedFromMasterPage (and must re-establish this association on each and every postback). Note that the Master property provides a strongly-typed experience. This is because I used the @MasterType directive in the .aspx file for this content page.

    The content page is updated by the selected drop-down list item in the Master Page.

    Conclusion
    Ideally Master Pages and their content pages will be completely independent entities with no need to share information. However, there are scenarios where this cannot be avoided without difficulty. For those situations, there are various techniques, as discussed in this article. To pass information from a content page to a Master Page, the content page can get a strongly-typed reference to the Master Page through use of the @MasterType directive. This allows the Master Page's public methods and properties to be invoked from content pages with the benefits of compile-time type checking. When passing information from the Master Page to its content pages, I've found the best approach is to have the Master Page raise an event and pass the necessary information. Those pages that need to be notified, then, can subscribe to this event.

    魔兽就是毒瘤,大家千万不要玩。
  • 相关阅读:
    MyBatis学习之二----应用
    网逛收藏
    Dubbo+Zookeeper 入门Demo
    React + umi +antd+antv/g6 实现力图
    npm、yarn 简单使用记录
    React yarn安装umi后 umi -v查询版本失败
    Eclipse 快速打开文件所在的本地目录
    Windows激活工具
    Win7 node多版本管理gnvm采坑记录
    自定义环形进度条RoundProgressBar
  • 原文地址:https://www.cnblogs.com/tracy/p/1783015.html
Copyright © 2011-2022 走看看