Udostępnij za pośrednictwem


Programowe określanie strony wzorcowej (VB)

Autor: Scott Mitchell

Sprawdza, czy strona wzorcowa strony zawartości jest programowo ustawiana za pomocą programu obsługi zdarzeń PreInit.

Wprowadzenie

Ponieważ przykład inauguracyjny w temacie Tworzenie układu całego witryny przy użyciu stron wzorcowych, wszystkie strony zawartości odwoływali się deklaratywnie do strony wzorcowej za pośrednictwem atrybutu MasterPageFile @Page w dyrektywie. Na przykład następująca @Page dyrektywa łączy stronę zawartości ze stroną Site.masterwzorcową :

<%@ Page Language="C#" MasterPageFile="~/Site.master"... %>

Klasa Page w System.Web.UI przestrzeni nazw zawiera MasterPageFile właściwość, która zwraca ścieżkę do strony wzorcowej strony zawartości. Jest to ta właściwość ustawiona przez dyrektywę@Page. Tej właściwości można również użyć do programowego określenia strony wzorcowej strony zawartości. Takie podejście jest przydatne, jeśli chcesz dynamicznie przypisywać stronę wzorcową na podstawie czynników zewnętrznych, takich jak użytkownik odwiedzający stronę.

W tym samouczku dodajemy drugą stronę wzorcową do naszej witryny internetowej i dynamicznie decydujemy, która strona wzorcowa ma być używana w czasie wykonywania.

Krok 1. Spojrzenie na cykl życia strony

Za każdym razem, gdy żądanie pojawi się na serwerze sieci Web dla strony ASP.NET, która jest stroną zawartości, aparat ASP.NET musi połączyć kontrolki Zawartość strony do odpowiednich kontrolek ContentPlaceHolder strony wzorcowej. To połączenie tworzy jedną hierarchię sterowania, która może następnie przejść przez typowy cykl życia strony.

Rysunek 1 ilustruje to połączenie. Krok 1 na rysunku 1 przedstawia początkową zawartość i hierarchie sterowania stroną wzorcową. Na końcu etapu PreInit kontrolki Zawartość na stronie są dodawane do odpowiednich symboli ContentPlaceHolders na stronie wzorcowej (krok 2). Po tym połączeniu strona wzorcowa służy jako katalog główny połączonej hierarchii sterowania. Ta połączona hierarchia sterowania jest następnie dodawana do strony w celu utworzenia finalizowanej hierarchii sterowania (krok 3). Wynikiem netto jest to, że hierarchia sterowania strony obejmuje bezpieczną hierarchię sterowania.

Hierarchie kontroli strony wzorcowej i strony zawartości są połączone razem podczas etapu preInit

Rysunek 01. Hierarchie kontroli strony wzorcowej i strony zawartości są połączone razem podczas etapu preInit (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 2. UstawianieMasterPageFilewłaściwości z kodu

Zawartość strony wzorcowej w tym połączeniu zależy od wartości Page właściwości obiektu MasterPageFile . Ustawienie atrybutu MasterPageFile @Page w dyrektywie ma wpływ netto na przypisanie Pagewłaściwości " MasterPageFile w etapie inicjowania, który jest pierwszym etapem cyklu życia strony. Alternatywnie można ustawić tę właściwość programowo. Należy jednak ustawić tę właściwość przed połączeniem na rysunku 1.

Na początku etapu Page PreInit obiekt zgłasza zdarzenie PreInit i wywołuje jego OnPreInit metodę. Aby ustawić stronę wzorcową programowo, możemy utworzyć program obsługi zdarzeń dla PreInit zdarzenia lub zastąpić metodę OnPreInit . Przyjrzyjmy się obu metodom.

Zacznij od otwarcia Default.aspx.vbpliku klasy za kodem dla strony głównej naszej witryny. Dodaj procedurę obsługi zdarzeń dla zdarzenia strony PreInit , wpisując następujący kod:

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
End Sub

W tym miejscu możemy ustawić MasterPageFile właściwość . Zaktualizuj kod, aby przypisywać wartość "~/Site.master" do MasterPageFile właściwości .

Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreInit 
 Me.MasterPageFile = "~/Site.master"
End Sub

Jeśli ustawisz punkt przerwania i zaczniesz od debugowania, zobaczysz, że za każdym razem Default.aspx , gdy strona zostanie odwiedzona lub gdy nastąpi powrót do tej strony, Page_PreInit program obsługi zdarzeń zostanie wykonany i MasterPageFile właściwość zostanie przypisana do "~/Site.master".

Alternatywnie można zastąpić metodę Page klasy OnPreInit i ustawić MasterPageFile tam właściwość . W tym przykładzie nie ustawimy strony wzorcowej w określonej stronie, ale raczej na stronie BasePage. Pamiętaj, że utworzyliśmy niestandardową klasę strony bazowej (BasePage) z powrotem w samouczku Określanie tytułu, tagów meta i innych nagłówków HTML na stronie wzorcowej. Obecnie BasePage zastępuje Page metodę klasy OnLoadComplete , w której ustawia właściwość strony Title na podstawie danych mapy witryny. Zaktualizujmy BasePage również metodę OnPreInit , aby programowo określić stronę wzorcową.

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 Me.MasterPageFile = "~/Site.master" 
 MyBase.OnPreInit(e)
End Sub

Ponieważ wszystkie nasze strony zawartości pochodzą z BasePageprogramu , wszystkie z nich mają teraz przypisaną programowo stronę wzorcową. W tym momencie PreInit program obsługi zdarzeń jest Default.aspx.vb zbędny; możesz go usunąć.

Co z dyrektywą@Page?

Co może być nieco mylące jest to, że właściwości stron MasterPageFile zawartości są teraz określane w dwóch miejscach: programowo w BasePage metodzie klasy OnPreInit , a także za pośrednictwem atrybutu MasterPageFile w dyrektywie każdej strony @Page zawartości.

Pierwszym etapem cyklu życia strony jest etap inicjowania. Na tym etapie Page właściwość obiektu MasterPageFile jest przypisywana wartość atrybutu MasterPageFile w @Page dyrektywie (jeśli jest podana). Etap PreInit jest zgodny z etapem Inicjowanie i tutaj programowo ustawiamy Page właściwość obiektu MasterPageFile , zastępując tym samym wartość przypisaną z @Page dyrektywy. Ponieważ programowo ustawiamy Page właściwość obiektu MasterPageFile , możemy usunąć MasterPageFile atrybut z @Page dyrektywy bez wpływu na środowisko użytkownika końcowego. Aby przekonać się o tym, przejdź do przodu i usuń MasterPageFile atrybut z @Page dyrektywy w Default.aspx programie , a następnie odwiedź stronę za pośrednictwem przeglądarki. Jak można się spodziewać, dane wyjściowe są takie same jak przed usunięciem atrybutu.

Określa, MasterPageFile czy właściwość jest ustawiana za pośrednictwem @Page dyrektywy, czy programowo, jest niekonsekwencyjna dla środowiska użytkownika końcowego. MasterPageFile Jednak atrybut w @Page dyrektywie jest używany przez program Visual Studio w czasie projektowania do tworzenia widoku WYSIWYG w Projektancie. Jeśli wrócisz do programu Visual Studio i przejdziesz do Default.aspx projektanta, zobaczysz komunikat "Błąd strony wzorcowej: Strona wzorcowa zawiera kontrolki wymagające odwołania do strony wzorcowej, ale nie określono jej" (zobacz Rysunek 2).

Krótko mówiąc, należy pozostawić MasterPageFile atrybut w @Page dyrektywie, aby cieszyć się bogatym środowiskiem czasu projektowania w programie Visual Studio.

Program Visual Studio używa klasy <span= atrybut masterPageFile dyrektywy @Page renderowania widoku projektu" />

Rysunek 02. Program Visual Studio używa atrybutu @Page dyrektywy do renderowania MasterPageFile widoku projektu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 3. Tworzenie alternatywnej strony wzorcowej

Ponieważ strona wzorcowa strony zawartości może być ustawiana programowo w czasie wykonywania, można dynamicznie załadować określoną stronę wzorcową na podstawie niektórych kryteriów zewnętrznych. Ta funkcja może być przydatna w sytuacjach, gdy układ witryny musi się różnić w zależności od użytkownika. Na przykład aplikacja internetowa aparatu blogu może zezwolić swoim użytkownikom na wybór układu dla swojego bloga, w którym każdy układ jest skojarzony z inną stroną wzorcową. W czasie wykonywania, gdy gość wyświetla blog użytkownika, aplikacja internetowa musi określić układ blogu i dynamicznie skojarzyć odpowiednią stronę wzorcową ze stroną zawartości.

Sprawdźmy, jak dynamicznie ładować stronę wzorcową w czasie wykonywania na podstawie niektórych kryteriów zewnętrznych. Nasza witryna internetowa zawiera obecnie tylko jedną stronę wzorcową (Site.master). Potrzebujemy innej strony wzorcowej, aby zilustrować wybór strony wzorcowej w czasie wykonywania. Ten krok koncentruje się na tworzeniu i konfigurowaniu nowej strony wzorcowej. Krok 4 analizuje sposób określania, która strona wzorcowa ma być używana w czasie wykonywania.

Utwórz nową stronę wzorcową w folderze głównym o nazwie Alternate.master. Dodaj również nowy arkusz stylów do witryny internetowej o nazwie AlternateStyles.css.

Dodawanie innej strony wzorcowej i pliku CSS do witryny sieci Web

Rysunek 03. Dodawanie kolejnej strony wzorcowej i pliku CSS do witryny sieci Web (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zaprojektowałem stronę wzorcową Alternate.master , aby tytuł był wyświetlany w górnej części strony, wyśrodkowany i na granatowym tle. Zrezygnowano z lewej kolumny i przeniesiono zawartość poniżej MainContent kontrolki ContentPlaceHolder, która teraz obejmuje całą szerokość strony. Ponadto nixed lista nieurządkowanych lekcji i zastąpiła ją poziomą listą powyżej MainContent. Zaktualizowałem również czcionki i kolory używane przez stronę wzorcową (i, przez rozszerzenie, jej strony zawartości). Rysunek 4 przedstawia Default.aspx użycie strony wzorcowej Alternate.master .

Uwaga

ASP.NET obejmuje możliwość definiowania motywów. Motyw to kolekcja obrazów, plików CSS i ustawień właściwości kontrolki sieci Web związanych ze stylem, które można zastosować do strony w czasie wykonywania. Motywy to sposób, aby przejść, jeśli układy witryny różnią się tylko w wyświetlanych obrazach i zgodnie z ich regułami CSS. Jeśli układy różnią się znacznie bardziej, na przykład przy użyciu różnych kontrolek sieci Web lub o radykalnie innym układzie, konieczne będzie użycie oddzielnych stron wzorcowych. Aby uzyskać więcej informacji na temat motywów, zapoznaj się z sekcją Dalsze informacje na końcu tego samouczka.

Nasze strony zawartości mogą teraz używać nowego wyglądu i działania

Rysunek 04. Nasze strony zawartości mogą teraz używać nowego wyglądu i działania (kliknij, aby wyświetlić obraz pełnowymiarowy)

Gdy znaczniki stron wzorcowych i zawartości są połączone, klasa sprawdza, MasterPage czy każda kontrolka Zawartość na stronie zawartości odwołuje się do elementu ContentPlaceHolder na stronie wzorcowej. Wyjątek jest zgłaszany, jeśli zostanie znaleziona kontrolka Zawartość odwołująca się do nieistniejącego symbolu ContentPlaceHolder. Innymi słowy, konieczne jest, aby strona wzorcowa przypisana do strony zawartości miała symbol ContentPlaceHolder dla każdej kontrolki Zawartość na stronie zawartości.

Strona wzorcowa Site.master zawiera cztery kontrolki ContentPlaceHolder:

  • head
  • MainContent
  • QuickLoginUI
  • LeftColumnContent

Niektóre strony zawartości w naszej witrynie internetowej obejmują tylko jedną lub dwie kontrolki Zawartości; inne zawierają kontrolkę Zawartość dla każdego z dostępnych symboli ContentPlaceHolders. Jeśli nasza nowa strona wzorcowa (Alternate.master) może być kiedykolwiek przypisana do tych stron zawartości, które mają kontrolki Zawartość dla wszystkich symboli ContentPlaceHolder w systemie Site.master , niezbędne Alternate.master jest również uwzględnienie tych samych kontrolek ContentPlaceHolder co Site.master.

Aby strona Alternate.master wzorcowa wyglądała podobnie do mojej (zobacz Rysunek 4), zacznij od zdefiniowania stylów strony wzorcowej w arkuszu AlternateStyles.css stylów. Dodaj następujące reguły do elementu AlternateStyles.css:

body 
{
 font-family: Comic Sans MS, Arial; 
 font-size: medium; 
 margin: 0px; 
} 
#topContent 
{ 
 text-align: center; 
 background-color: Navy; 
 color: White; 
 font-size: x-large;
 text-decoration: none; 
 font-weight: bold; 
 padding: 10px; 
 height: 50px;
} 
#topContent a 
{ 
 text-decoration: none; 
 color: White; 
} 
#navContent 
{ 
 font-size: small; 
 text-align: center; 
} 
#footerContent 
{ 
 padding: 10px; 
 font-size: 90%; 
 text-align: center; 
 border-top: solid 1px black; 
} 
#mainContent 
{ 
 text-align: left; 
 padding: 10px;
}

Następnie dodaj następujący znacznik deklaratywny do .Alternate.master Jak widać, Alternate.master zawiera cztery kontrolki ContentPlaceHolder z tymi samymi ID wartościami co kontrolki ContentPlaceHolder w pliku Site.master. Ponadto zawiera kontrolkę ScriptManager, która jest niezbędna dla tych stron w naszej witrynie internetowej korzystającej z platformy ASP.NET AJAX.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head id="Head1" runat="server"> 
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder> 
 <link href="AlternateStyles.css" rel="stylesheet" type="text/css"/> 
</head> 
<body> 
 <form id="form1" runat="server"> 
 <asp:ScriptManager ID="MyManager" runat="server"> 
 </asp:ScriptManager>
 <div id="topContent">
 <asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx" 
 Text="Master Pages Tutorials" /> 
 </div>
 <div id="navContent"> 
 <asp:ListView ID="LessonsList" runat="server" 
 DataSourceID="LessonsDataSource">
 <LayoutTemplate>
 <asp:PlaceHolder runat="server" ID="itemPlaceholder" /> 
 </LayoutTemplate>
 <ItemTemplate>
 <asp:HyperLink runat="server" ID="lnkLesson" 
 NavigateUrl='<%# Eval("Url") %>' 
 Text='<%# Eval("Title") %>' /> 
 </ItemTemplate>
 <ItemSeparatorTemplate> | </ItemSeparatorTemplate> 
 </asp:ListView>
 <asp:SiteMapDataSource ID="LessonsDataSource" runat="server" 
 ShowStartingNode="false" /> 
 </div> 
 <div id="mainContent">
 <asp:ContentPlaceHolder id="MainContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div>
 <div id="footerContent">
 <p> 
 <asp:Label ID="DateDisplay" runat="server"></asp:Label> 
 </p>
 <asp:ContentPlaceHolder ID="QuickLoginUI" runat="server"> 
 </asp:ContentPlaceHolder>
 <asp:ContentPlaceHolder ID="LeftColumnContent" runat="server"> 
 </asp:ContentPlaceHolder>
 </div> 
 </form>
</body> 
</html>

Testowanie nowej strony wzorcowej

Aby przetestować tę nową stronę wzorcową, zaktualizuj BasePage metodę klasy OnPreInit , aby MasterPageFile właściwość została przypisana do wartości "~/Alternate.maser" , a następnie odwiedź witrynę internetową. Każda strona powinna działać bez błędu z wyjątkiem dwóch: ~/Admin/AddProduct.aspx i ~/Admin/Products.aspx. Dodanie produktu do kontrolki DetailsView powoduje ~/Admin/AddProduct.aspx wyświetlenie NullReferenceException elementu z wiersza kodu, który próbuje ustawić właściwość strony wzorcowej GridMessageText . Podczas odwiedzania ~/Admin/Products.aspx obiektu InvalidCastException jest zgłaszany podczas ładowania strony z komunikatem: "Nie można rzutować obiektu typu "ASP.alternate_master", aby wpisać "ASP.site_master".

Te błędy występują, ponieważ Site.master klasa za kodem zawiera zdarzenia publiczne, właściwości i metody, które nie są zdefiniowane w programie Alternate.master. Część znaczników tych dwóch stron ma dyrektywę odwołującą @MasterType się do strony wzorcowej Site.master .

<%@ MasterType VirtualPath="~/Site.master" %>

Ponadto program obsługi zdarzeń Elementu DetailsView ItemInserted w programie ~/Admin/AddProduct.aspx zawiera kod, który rzutuje luźno typizowane Page.Master właściwości na obiekt typu Site. @MasterType Dyrektywa (używana w ten sposób) i rzutowanie w ItemInserted procedurze obsługi zdarzeń ściśle łączy ~/Admin/AddProduct.aspx strony i ~/Admin/Products.aspx ze stroną wzorcowąSite.master.

Aby przerwać to ścisłe sprzężenie, możemy mieć Site.master i Alternate.master pochodzić z wspólnej klasy bazowej, która zawiera definicje dla publicznych elementów członkowskich. Następnie możemy zaktualizować dyrektywę @MasterType , aby odwoływać się do tego wspólnego typu podstawowego.

Tworzenie niestandardowej podstawowej klasy strony wzorcowej

Dodaj nowy plik klasy do App_Code folderu o nazwie BaseMasterPage.vb i utwórz go na podstawie .System.Web.UI.MasterPage Musimy zdefiniować metodę RefreshRecentProductsGrid i GridMessageText właściwość w BaseMasterPagepliku , ale nie możemy po prostu przenieść ich tam, Site.master ponieważ te elementy członkowskie współpracują z kontrolkami sieci Web specyficznymi dla Site.master strony wzorcowej ( RecentProducts GridView i GridMessage Label).

To, co musimy zrobić, to skonfigurować BaseMasterPage w taki sposób, że te składowe są tam zdefiniowane, ale są faktycznie implementowane przez BaseMasterPageklasy pochodne (Site.master i Alternate.master). Ten typ dziedziczenia jest możliwy przez oznaczenie klasy jako MustInherit i jej składowych jako MustOverride. Krótko mówiąc, dodanie tych słów kluczowych do klasy i jej dwóch składowych informuje, że BaseMasterPage nie zaimplementowano RefreshRecentProductsGrid i GridMessageText, ale jego klasy pochodne będą.

Musimy również zdefiniować PricesDoubled zdarzenie w BaseMasterPage obiekcie i dostarczyć środki przez klasy pochodne, aby zgłosić zdarzenie. Wzorzec używany w programie .NET Framework do ułatwienia tego zachowania polega na utworzeniu publicznego zdarzenia w klasie bazowej i dodaniu chronionej, zastępowalnej metody o nazwie OnEventName. Klasy pochodne mogą następnie wywołać tę metodę, aby zgłosić zdarzenie lub przesłonić go w celu wykonania kodu bezpośrednio przed lub po wywołaniu zdarzenia.

Zaktualizuj klasę BaseMasterPage tak, aby zawierała następujący kod:

Public MustInherit Class BaseMasterPage 
 Inherits System.Web.UI.MasterPage 
 Public Event PricesDoubled As EventHandler
 Protected Overridable Sub OnPricesDoubled(ByVal e As EventArgs)
 RaiseEvent PricesDoubled(Me, e)
 End Sub
 Public MustOverride Sub RefreshRecentProductsGrid() 
 Public MustOverride Property GridMessageText() As String 
End Class

Następnie przejdź do Site.master klasy za pomocą kodu i utwórz ją z klasy BaseMasterPage. Ponieważ BaseMasterPage zawiera elementy członkowskie oznaczone MustOverride , musimy zastąpić te elementy członkowskie w tym miejscu w pliku Site.master. Overrides Dodaj słowo kluczowe do definicji metody i właściwości. Zaktualizuj również kod, który zgłasza PricesDoubled zdarzenie w DoublePrice procedurze obsługi zdarzeń przycisku Click za pomocą wywołania metody klasy bazowej OnPricesDoubled .

Po tych modyfikacjach Site.master klasa za kodem powinna zawierać następujący kod:

Partial Class Site 
 Inherits BaseMasterPage
 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd")
 End Sub
 Public Overrides Sub RefreshRecentProductsGrid() 
 RecentProducts.DataBind()
 End Sub 
 Public Overrides Property GridMessageText() As String 
 Get
 Return GridMessage.Text
 End Get 
 Set(ByVal Value As String) 
 GridMessage.Text = Value 
 End Set
 End Property 
 Protected Sub DoublePrice_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DoublePrice.Click 
 ' Double the prices 
 DoublePricesDataSource.Update()
 ' Refresh RecentProducts 
 RecentProducts.DataBind()
 ' Raise the PricesDoubled event
 MyBase.OnPricesDoubled(EventArgs.Empty)
 End Sub 
End Class

Musimy również zaktualizować Alternate.masterklasę "code-behind", aby pochodzić z BaseMasterPage dwóch elementów członkowskich i zastąpić je MustOverride . Jednak ponieważ Alternate.master element GridView nie zawiera listy najnowszych produktów ani etykiety, która wyświetla komunikat po dodaniu nowego produktu do bazy danych, te metody nie muszą nic robić.

Partial Class Alternate 
 Inherits BaseMasterPage
 Public Overrides Property GridMessageText() As String 
 Get
 Return String.Empty
 End Get
 Set(ByVal value As String) 
 ' Do nothing 
 End Set 
 End Property 
 Public Overrides Sub RefreshRecentProductsGrid()
 ' Do nothing 
 End Sub 
End Class

Odwoływanie się do podstawowej klasy strony wzorcowej

Teraz, gdy ukończyliśmy klasę BaseMasterPage i rozszerzyliśmy dwie strony wzorcowe, ostatnim krokiem jest zaktualizowanie ~/Admin/AddProduct.aspx stron i ~/Admin/Products.aspx w celu odwołania się do tego wspólnego typu. Zacznij od zmiany @MasterType dyrektywy na obu stronach:

<%@ MasterType VirtualPath="~/Site.master" %>

Do:

<%@ MasterType TypeName="BaseMasterPage" %>

Zamiast odwoływać się do ścieżki pliku, @MasterType właściwość odwołuje się teraz do typu podstawowego (BaseMasterPage). W związku z tym silnie typizowana Master właściwość używana w klasach za kodem obu stron jest teraz typu BaseMasterPage (zamiast typu Site). Po tej zmianie ponownie przejdź ~/Admin/Products.aspxdo elementu . Wcześniej spowodowało to błąd rzutowania, ponieważ strona jest skonfigurowana do używania strony wzorcowej Alternate.master , ale @MasterType dyrektywa odwołuje się Site.master do pliku. Ale teraz strona jest renderowana bez błędu. Dzieje się tak, ponieważ strona wzorcowa Alternate.master może być rzutowa na obiekt typu BaseMasterPage (ponieważ rozszerza ją).

Istnieje jedna mała zmiana, która musi zostać wprowadzona w pliku ~/Admin/AddProduct.aspx. Procedura obsługi zdarzeń kontrolki ItemInserted DetailsView używa zarówno właściwości silnie typizowanej Master , jak i luźno typizowanej Page.Master właściwości. Usunęliśmy silnie typizowane odwołanie podczas aktualizowania @MasterType dyrektywy, ale nadal musimy zaktualizować luźno wpisane odwołanie. Zastąp następujący wiersz kodu:

Dim myMasterPage As Site = CType(Page.Master, Site)

Za pomocą następującej metody rzutowania Page.Master na typ podstawowy:

Dim myMasterPage As BaseMasterPage = CType(Page.Master, BaseMasterPage)

Krok 4. Określanie, która strona wzorcowa ma być powiązana ze stronami zawartości

Nasza BasePage klasa ustawia obecnie właściwości wszystkich stron MasterPageFile zawartości na wartość zakodowaną w fazie PreInit cyklu życia strony. Ten kod można zaktualizować, aby oprzeć stronę wzorcową na pewnym czynniku zewnętrznym. Być może strona wzorcowa do załadowania zależy od preferencji aktualnie zalogowanego użytkownika. W takim przypadku musimy napisać kod w metodzie OnPreInit BasePage , który wyszukuje aktualnie odwiedzające preferencje strony wzorcowej użytkownika.

Utwórzmy stronę internetową, która umożliwia użytkownikowi wybranie strony wzorcowej do użycia — Site.master lub Alternate.master — i zapisanie tego wyboru w zmiennej Sesja. Zacznij od utworzenia nowej strony internetowej w katalogu głównym o nazwie ChooseMasterPage.aspx. Podczas tworzenia tej strony (lub innych stron zawartości w związku z tym) nie trzeba powiązać jej ze stroną wzorcową, ponieważ strona wzorcowa jest ustawiana programowo w programie BasePage. Jeśli jednak nie powiążesz nowej strony ze stroną wzorcową, domyślny znacznik deklaratywny nowej strony zawiera formularz internetowy i inną zawartość dostarczaną przez stronę wzorcową. Należy ręcznie zastąpić ten znacznik odpowiednimi kontrolkami Zawartości. Z tego powodu łatwiej jest powiązać nową stronę ASP.NET ze stroną wzorcową.

Uwaga

Ponieważ Site.master i Alternate.master mają ten sam zestaw kontrolek ContentPlaceHolder, nie ma znaczenia, jaką stronę wzorcową wybierasz podczas tworzenia nowej strony zawartości. W celu zapewnienia spójności proponuję użycie polecenia Site.master.

Dodawanie nowej strony zawartości do witryny internetowej

Rysunek 05. Dodawanie nowej strony zawartości do witryny sieci Web (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zaktualizuj plik, Web.sitemap aby uwzględnić wpis dla tej lekcji. Dodaj następujący znacznik poniżej <siteMapNode> strony wzorcowej i ASP.NET LEKCJI AJAX:

<siteMapNode url="~/ChooseMasterPage.aspx" title="Choose a Master Page" />

Przed dodaniem jakiejkolwiek zawartości do ChooseMasterPage.aspx strony pośmiń chwilę, aby zaktualizować klasę kodową strony w taki sposób, aby pochodziła z BasePage klasy (a nie System.Web.UI.Page). Następnie dodaj kontrolkę DropDownList do strony, ustaw jej ID właściwość na MasterPageChoice, i dodaj dwie wartości ListItems z wartościami Text "~/Site.master" i "~/Alternate.master".

Dodaj kontrolkę Sieć Web przycisku do strony i ustaw jej ID Text właściwości odpowiednio na SaveLayout i "Zapisz wybór układu". Na tym etapie znaczniki deklaratywne strony powinny wyglądać podobnie do następujących:

<p> 
 Your layout choice: 
 <asp:DropDownList ID="MasterPageChoice" runat="server"> 
 <asp:ListItem>~/Site.master</asp:ListItem>
 <asp:ListItem>~/Alternate.master</asp:ListItem>
 </asp:DropDownList> 
</p> 
<p> 
 <asp:Button ID="SaveLayout" runat="server" Text="Save Layout Choice" /> 
</p>

Po pierwszym odwiedzeniu strony musimy wyświetlić aktualnie wybraną stronę wzorcową użytkownika. Utwórz procedurę obsługi zdarzeń Page_Load i dodaj następujący kod:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 If Session("MyMasterPage") IsNot Nothing Then 
 Dim li As ListItem = MasterPageChoice.Items.FindByText(Session("MyMasterPage").ToString())
 If li IsNot Nothing Then 
 li.Selected = True
 End If 
 End If 
 End If 
End Sub

Powyższy kod jest wykonywany tylko podczas pierwszej wizyty na stronie (a nie podczas kolejnych ogłaszań zwrotnych). Najpierw sprawdza, czy zmienna MyMasterPage sesji istnieje. Jeśli tak, próbuje znaleźć pasujący element ListItem w liście rozwijanej MasterPageChoice . Jeśli zostanie znaleziony pasujący element ListItem, jego Selected właściwość jest ustawiona na Truewartość .

Potrzebujemy również kodu, który zapisuje wybór użytkownika w zmiennej MyMasterPage Sesja. Utwórz procedurę obsługi zdarzeń dla SaveLayout zdarzenia przycisku Click i dodaj następujący kod:

Protected Sub SaveLayout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveLayout.Click 
 Session("MyMasterPage") = MasterPageChoice.SelectedValue 
 Response.Redirect("ChooseMasterPage.aspx")
End Sub

Uwaga

Click Gdy program obsługi zdarzeń zostanie wykonany po powłoce, strona wzorcowa została już wybrana. W związku z tym wybór listy rozwijanej użytkownika nie będzie obowiązywać, dopóki następna strona nie zostanie wyświetlona. Wymusza Response.Redirect ponowne żądanie ChooseMasterPage.aspxw przeglądarce .

Po zakończeniu ChooseMasterPage.aspx strony naszym ostatnim zadaniem jest BasePage przypisanie MasterPageFile właściwości na podstawie wartości zmiennej MyMasterPage Sesja. Jeśli zmienna sesji nie jest ustawiona, ma BasePage wartość domyślną Site.master.

Protected Overrides Sub OnPreInit(ByVal e As System.EventArgs)
 SetMasterPageFile() 
 MyBase.OnPreInit(e)
End Sub 
Protected Overridable Sub SetMasterPageFile() 
 Me.MasterPageFile = GetMasterPageFileFromSession() 
End Sub 
Protected Function GetMasterPageFileFromSession() As String 
 If Session("MyMasterPage") Is Nothing Then
 Return "~/Site.master"
 Else 
 Return Session("MyMasterPage").ToString() 
 End If 
End Function

Uwaga

Przeniesiono kod, który przypisuje Page właściwość obiektu MasterPageFile poza OnPreInit procedurę obsługi zdarzeń i do dwóch oddzielnych metod. Ta pierwsza metoda, SetMasterPageFile, przypisuje MasterPageFile właściwość do wartości zwracanej przez drugą metodę GetMasterPageFileFromSession. Oznaczyłem metodę SetMasterPageFile Overridable tak, aby przyszłe klasy rozszerzające BasePage mogły opcjonalnie zastąpić ją w celu zaimplementowania logiki niestandardowej, jeśli jest to konieczne. W następnym samouczku zobaczymy przykład zastępowania BasePagewłaściwości .s SetMasterPageFile .

Za pomocą tego kodu odwiedź ChooseMasterPage.aspx stronę. Site.master Początkowo wybrano stronę wzorcową (zobacz Rysunek 6), ale użytkownik może wybrać inną stronę wzorcową z listy rozwijanej.

Strony zawartości są wyświetlane przy użyciu strony wzorcowej Site.master

Rysunek 06. Strony zawartości są wyświetlane przy użyciu strony wzorcowej Site.master (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Strony zawartości są teraz wyświetlane przy użyciu strony wzorcowej Alternate.master

Rysunek 07. Strony zawartości są teraz wyświetlane przy użyciu strony wzorcowej Alternate.master (kliknij, aby wyświetlić obraz pełnowymiarowy)

Podsumowanie

Po odwiedzeniu strony zawartości jej kontrolki Zawartość są połączone z kontrolkami ContentPlaceHolder strony wzorcowej. Strona wzorcowa strony zawartości jest oznaczona właściwością Page klasy MasterPageFile , która jest przypisywana do @Page atrybutu dyrektywy MasterPageFile podczas etapu inicjowania. Jak pokazano w tym samouczku, możemy przypisać wartość do MasterPageFile właściwości tak długo, jak to zrobimy przed końcem etapu PreInit. Możliwość programowego określenia strony wzorcowej otwiera drzwi dla bardziej zaawansowanych scenariuszy, takich jak dynamiczne powiązanie strony zawartości ze stroną wzorcową na podstawie czynników zewnętrznych.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

Informacje o autorze

Scott Mitchell, autor wielu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 3,5 w ciągu 24 godzin. Scott można uzyskać na mitchell@4GuysFromRolla.com stronie lub za pośrednictwem swojego bloga pod adresem http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Recenzentem tego samouczka był Suchi Banerjee. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com