Programowe określanie strony wzorcowej (VB)

Autor : Scott Mitchell

Przyjrzyj się programowemu ustawianiu strony wzorcowej strony zawartości za pośrednictwem programu obsługi zdarzeń PreInit.

Wprowadzenie

Ponieważ inauguracyjny przykład w artykule Tworzenie układu Site-Wide 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"... %>

KlasaPage 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ść, która jest ustawiana 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 przypisać 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 dotrze do serwera internetowego dla strony ASP.NET będącej stroną zawartości, aparat ASP.NET musi połączyć kontrolki Zawartość strony z odpowiednimi kontrolkami 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 kontrolek strony wzorcowej. Na końcu etapu PreInit kontrolki Zawartość na stronie są dodawane do odpowiednich symboli ContentPlaceHolder na stronie wzorcowej (Krok 2). Po tym połączeniu strona wzorcowa służy jako katalog główny hierarchii kontroli połączonej. 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 zawiera bezpieczną hierarchię sterowania.

Hierarchie kontrolek 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 poziomu kodu

To, co partykuje strona wzorcowa MasterPageFile w tym połączeniu, zależy od wartości Page właściwości obiektu. Ustawienie atrybutu MasterPageFile@Page w dyrektywie ma wpływ netto na przypisanie Pagewłaściwości "w MasterPageFile etapie inicjowania, który jest pierwszym etapem cyklu życia strony. Tę właściwość można też ustawić programowo. Jednak przed wykonaniem łączenia na rysunku 1 należy ustawić tę właściwość.

Na początku etapu Page PreInit obiekt zgłasza zdarzeniePreInit 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 podejść.

Zacznij od otwarcia Default.aspx.vbpliku klasy kodu 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 procedura obsługi zdarzeń zostanie wykonana i MasterPageFile właściwość zostanie przypisana do "~/Site.master".

Alternatywnie można zastąpić metodę Page klasy OnPreInit i ustawić MasterPageFile w niej właściwość . W tym przykładzie nie ustawimy strony wzorcowej w określonej stronie, ale raczej z .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ę , aby zastąpić metodę OnPreInit programowo określającą 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ń w Default.aspx.vb programie jest 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 pomocą atrybutu MasterPageFile w dyrektywie każdej strony @Page zawartości.

Pierwszym etapem cyklu życia strony jest etap inicjowania. Podczas tego etapu 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 w ten sposób wartość przypisaną z @Page dyrektywy . Ponieważ ustawiamy Page właściwość obiektu MasterPageFile programowo, 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 , a następnie odwiedź stronę za pośrednictwem przeglądarki. Jak można oczekiwać, dane wyjściowe są takie same jak przed usunięciem atrybutu.

Określa, MasterPageFile czy właściwość jest ustawiana za pomocą @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 Projektant. Jeśli wrócisz do Default.aspx programu Visual Studio i przejdziesz do Projektant zostanie wyświetlony komunikat "Błąd strony wzorcowej: Strona zawiera kontrolki wymagające odwołania do strony wzorcowej, ale nie jest określona" (zobacz Rysunek 2).

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

Program Visual Studio używa atrybutu MasterPageFile dyrektywy <span @Page do renderowania widoku projektu " />

Rysunek 02. Program Visual Studio używa @Page atrybutu 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, w których 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 zał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 obejmuje określenie, 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 kolejnej 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 w pełnym rozmiarze)

Zaprojektowałem stronę wzorcową Alternate.master , aby tytuł wyświetlany w górnej części strony, wyśrodkowany i na granatowym tle. Zostałem zwolniony z lewej kolumny i przeniesiono zawartość poniżej MainContent kontrolki ContentPlaceHolder, która teraz obejmuje całą szerokość strony. Co więcej, mam nixed nieurządkowaną listę lekcji i zastąpiłem ją poziomą listą powyżej MainContent. Zaktualizowałem również czcionki i kolory używane przez stronę wzorcową (i, według rozszerzenia, 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 są sposobem, aby przejść, jeśli układy witryny różnią się tylko wyświetlanymi obrazami i regułami CSS. Jeśli układy różnią się znacznie bardziej, na przykład przy użyciu różnych kontrolek sieci Web lub mają radykalnie inny układ, należy użyć 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 korzystać z 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 w pełnym rozmiarze)

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 Content odwołująca się do nieistniejącego symbolu ContentPlaceHolder. Innymi słowy, konieczne jest, aby strona wzorcowa przypisana do strony zawartości miała właściwość 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 zawierają tylko jedną lub dwie kontrolki zawartości; inne zawierają kontrolkę Zawartość dla każdego z dostępnych symboli ContentPlaceHolder. Jeśli nasza nowa strona wzorcowa (Alternate.master) może kiedykolwiek zostać przypisana do tych stron zawartości, które mają kontrolki Zawartość dla wszystkich elementów ContentPlaceHolder w elemecie Site.master , istotne jest, aby Alternate.master zawierały również te same kontrolki 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 elementu 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 tak, 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łędów z wyjątkiem dwóch: ~/Admin/AddProduct.aspx i ~/Admin/Products.aspx. Dodanie produktu do elementu DetailsView powoduje ~/Admin/AddProduct.aspxNullReferenceException wyświetlenie kodu 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 Alternate.masterprogramie . Część znaczników tych dwóch stron zawiera 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 typową Page.Master właściwość na obiekt typu Site. Dyrektywa @MasterType (używana w ten sposób) i rzutowanie w procedurze obsługi zdarzeń ItemInserted ś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. W związku z tym 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.MasterPageelementu . Musimy zdefiniować metodę RefreshRecentProductsGrid i GridMessageText właściwość w BaseMasterPageprogramie , ale nie możemy po prostu przenieść ich tam, Site.master ponieważ członkowie 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 elementy członkowskie są tam zdefiniowane, ale są rzeczywiście 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 członków ogłasza, że BaseMasterPage nie zaimplementowano RefreshRecentProductsGrid i GridMessageText, ale jego klasy pochodne będą.

Musimy również zdefiniować PricesDoubled zdarzenie w elemecie BaseMasterPage i podać metodę przez klasy pochodne, aby zgłosić zdarzenie. Wzorzec używany w .NET Framework w celu ułatwienia tego zachowania polega na utworzeniu zdarzenia publicznego 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 zastąpić go w celu wykonania kodu bezpośrednio przed lub po wywołaniu zdarzenia.

Zaktualizuj klasę, BaseMasterPage 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 code-behind i utwórz ją na podstawie BaseMasterPagemetody . 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 wprowadzeniu tych modyfikacji Site.master klasa code-behind 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 . Ale 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 klasy podstawowej strony wzorcowej

Teraz, gdy ukończyliśmy klasę BaseMasterPage i rozszerzyliśmy dwie strony wzorcowe, naszym ostatnim krokiem jest zaktualizowanie ~/Admin/AddProduct.aspx stron i ~/Admin/Products.aspx w celu odwoływania 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 kodowych obu stron jest teraz typu BaseMasterPage (zamiast typu Site). Dzięki tej zmianie ponownie nastąpi ponowne ponowne wprowadzenie ~/Admin/Products.aspx. Wcześniej spowodowało to błąd rzutowania, ponieważ strona jest skonfigurowana do używania Alternate.master strony wzorcowej, ale @MasterType dyrektywa odwołuje się Site.master do pliku. Ale teraz strona jest renderowana bez błędu. Wynika to z faktu, że strona wzorcowa Alternate.master może być rzutowania do obiektu typu BaseMasterPage (ponieważ rozszerza ją).

Istnieje jedna mała zmiana, która musi zostać wprowadzona w ~/Admin/AddProduct.aspxpliku . Procedura obsługi zdarzeń kontrolki ItemInserted DetailsView używa zarówno silnie typizowanej Master właściwości, jak i luźno wpisanej Page.Master właściwości. Usunęliśmy silnie typizowane odwołanie, gdy zaktualizowaliśmy dyrektywę @MasterType , 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 strony wzorcowej do powiązania 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. Możemy zaktualizować ten kod, aby opierać stronę wzorcową na niektórych czynnikach zewnętrznych. Być może strona wzorcowa do załadowania zależy od preferencji aktualnie zalogowanego użytkownika. W takim przypadku musimy napisać kod w OnPreInit metodzie , który BasePage 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 sesji. 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ść dostarczoną 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 internetowej (kliknij, aby wyświetlić obraz pełnowymiarowy)

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 dowolnej zawartości do ChooseMasterPage.aspx strony należy chwilę zaktualizować klasę za pomocą kodu strony, aby mogła pochodzić 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 IDText właściwości odpowiednio na SaveLayout i "Zapisz wybór układu". Na tym etapie deklaratywne znaczniki 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>

Gdy strona zostanie po raz pierwszy odwiedzona, 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 w kolejnych postbackach). Najpierw sprawdza, czy zmienna MyMasterPage sesji istnieje. Jeśli tak, próbuje znaleźć pasujący listItem na 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

Po wykonaniu Click procedury obsługi zdarzeń po powrocie zwrotnej strona wzorcowa została już wybrana. W związku z tym wybór listy rozwijanej użytkownika nie będzie obowiązywać do czasu kolejnej wizyty strony. 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 wartość domyślną BasePageSite.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 zwróconej przez drugą metodę GetMasterPageFileFromSession. Oznaczyłem metodę Overridable takSetMasterPageFile, aby przyszłe klasy rozszerzające BasePage mogły opcjonalnie zastąpić ją w celu zaimplementowania logiki niestandardowej w razie potrzeby. 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 jest zaznaczona strona wzorcowa (patrz 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 pełnowymiarowy)

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, o ile to zrobimy przed końcem etapu PreInit. Możliwość programowego określenia strony wzorcowej powoduje otwarcie 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 dotrzeć pod mitchell@4GuysFromRolla.com adresem lub za pośrednictwem swojego bloga pod adresem http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została przejrzyona przez wielu przydatnych recenzentów. Głównym recenzentem tego samouczka był Suchi Banerjee. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi linię na mitchell@4GuysFromRolla.com