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.master
wzorcową :
<%@ 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.
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. UstawianieMasterPageFile
wł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 Page
wł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.vb
pliku 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 BasePage
programu , 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.
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
.
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.
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 BaseMasterPage
pliku , 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 BaseMasterPage
klasy 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.master
klasę "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.aspx
do 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
.
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 True
wartość .
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.aspx
w 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 BasePage
wł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.
Rysunek 06. Strony zawartości są wyświetlane przy użyciu strony wzorcowej Site.master
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
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:
- Przegląd cyklu życia strony ASP.NET
- ASP.NET motywy i skórki — omówienie
- Strony wzorcowe: porady, wskazówki i pułapki
- Motywy w ASP.NET
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