background image

Oddzielanie kodu od tre

ś

ci 

W osiemnastu poprzednich rozdziałach ksiąŜki przedstawionych zostało kilka sposobów na 
oddzielanie interfejsu uŜytkownika stron ASP.NET od kodu który go obsługuje (napisanego  w 
języku VB.NET). Przykładowo, zostały przedstawione sposoby przenoszenia kodu, który nie jest 
bezpośrednio związany z interfejsem uŜytkownika do obiektów biznesowych, dzięki czemu strony 
ASP.NET mogą zawierać wyłącznie kod związany z obsługą prezentacji danych. Co więcej, 
wszelkie polecenia SQL moŜna zapisać w bazie danych w formie procedur zachowanych i usunąć 
je ze stron ASP.NET (zagadnienia te zostały omówione w rozdziale 12., pt.: „Zastosowanie 
zaawansowanych technik obsługi danych”). Wszelkie ustawienia i zmienne moŜna natomiast 
zapisać w plikach konfiguracyjnych, takich jak 

web.config

W tym rozdziale zostanie przedstawionych kilka bardziej zaawansowanych metod separacji kodu 
ź

ródłowego od zawartości strony, czyli kodu kontrolującego działanie aplikacji od kodu 

odpowiedzialnego za prezentację danych (na przykład: elementów sterujących HTML oraz 
internetowych elementów sterujących). Programiści ASP.NET bardzo oczekiwali moŜliwości 
takiej separacji, gdyŜ dzięki nim moŜna uprościć strony i logicznie zgrupować wykorzystywany w 
nich kod. PrzecieŜ strony ASP.NET słuŜą wyłącznie do prezentacji interfejsu uŜytkownika, a 
zatem po co miałby być w nich umieszczany kod o innym przeznaczeniu? 

W tym rozdziale poznamy takŜe sposoby dostosowywania stron ASP.NET do pochodzenia 
uŜytkownika. Metody te pozwalają na modyfikację zawartości stron ASP.NET zupełnie 
niezaleŜnie od wydzielonego kodu stron. 

W tym rozdziale przedstawionych zostanie bardzo wiele przykładów, a zatem… zaczynajmy! 

W tym rozdziale zostaną omówione następujące zagadnienia: 

 

Czym jest kod obsługi formularzy? 

 

Jak uŜywać kodu obsługi przy tworzeniu stron ASP.NET. 

 

W jaki sposób elementy sterujące uŜytkownika mogą korzystać z kodu obsługi. 

 

Jak określić pochodzenie uŜytkownika (na podstawie uŜywanego języka). 

 

Jak określić informacje o kulturze i regionie uŜytkownika. 

 

W jaki sposób moŜna wydzielić ze stron ASP.NET najczęściej uŜywane łańcuchy 
znaków i zapisać je w niezaleŜnych plikach zasobów. 

Potrzeba rozdzielania ró

Ŝ

nych rodzajów 

kodu 

Być moŜe przypominasz sobie z dyskusji przedstawionej w rozdziale 2., Ŝe ASP.NET stara się 
uprościć Ŝycie programistom umoŜliwiając niezaleŜne grupowanie kodu ASP.NET oraz kodu 
HTML. Na przykład, większość (o ile nie cały) kod ASP.NET powinien być umieszczany w 
blokach 

SCRIPT

 na samym początku stron ASP.NET i oddzielony od kodu HTML. Oddzielenie 

obu rodzajów kodu zostało przedstawione na rysunku 19.1. 

 

background image

Kod ASP.NET 

<%@Page Language="VB" %> 
<%@Import Namespace="System.Xml" %> 
<%@Import Namespace="System.Xml.XPath" %> 
 
<script runat="server"> 
   sub SelectData(obj as object,e as eventargs) 
      Dim objDocument as New XPathDocument _ 
         (Server.MapPath("../r11/books.xml")) 
 
      Dim objNav as XPathNavigator = objDocument.CreateNavigator 
 
      lblMessage.Text = "" 
      try 
         dim objIterator as XPathNodeIterator = _ 
            objNav.Select(tbQuery.Text) 
   

 

         While objIterator.MoveNext() 
            lblMessage.Text += "&lt;" & _ 
               objIterator.Current.Name & "&gt; " & _ 
               objIterator.Current.Value & "<br>" 
         end while 
      catch ex As Exception 
         lblMessage.Text = ex.Message 
      end try 
   end sub 
</script> 

Kod HTML 

<html><body> 
   <form runat="server"> 
      <h2>Zapytania XPath</h2>  
      <p> 
      Na przyład:<br> 
      <b><code>//book[last()]/@ISBN/text()</b></code> lub  
      <b><code>descendant::book/author/last-name</b></code><p> 
       
      Podaj zapytanie XPath:  
      <asp:Textbox id="tbQuery" runat=server/> 
      <asp:Button id="btnSubmit" text="Wykonaj zapytanie" 
         runat=server OnClick="SelectData"/><p> 
      <asp:Label id="lblMessage" runat=server/> 
   </form> 
</body></html> 

 

Tworzenie kodu w sposób przedstawiony na rysunku 19.1 jest bardzo korzystne i to z wielu 
powodów — łatwiej moŜna modyfikować zarówno kod ASP.NET jak i kod HTML, kod źródłowy 
strony staje się w ten sposób bardziej logiczny i nie trzeba szukać w nim bloków kodu 
wykonywalnego. Niemniej jednak moŜliwości rozdzielania róŜnych rodzajów kodu jakie daje 
ASP.NET są jeszcze większe. Dzięki wykorzystaniu kodu obsługi oraz plików zasobów moŜna 
całkowicie oddzielić kod od zawartości strony. Pierwsze z powyŜszych rozwiązań umoŜliwia 
zapisywanie kodu w niezaleŜnych plikach, natomiast drugie — zgrupowanie często 
wykorzystywanych wartości (takich jak na przykład komunikaty o błędach) i zapisanie ich w 
jednym miejscu, niezaleŜnym od strony ASP.NET. 

Kod obsługi formularzy 

Patrząc na rysunek 19.1 nie trudno zauwaŜyć korzyści płynące z oddzielenia kodu od treści strony. 
Ale co by się stało, gdyby moŜna było usunąć całą początkową zawartość pliku 

.aspx

? Dzięki 

temu istniałaby moŜliwość faktycznego oddzielenia kod ASP.NET do zawartości strony. 
Technologia ASP.NET pozwala na osiągnięcie takiej separacji dzięki wykorzystaniu kodu obsługi 
formularzy. Kod obsługi formularzy jest sposobem na całkowite oddzielenie kaŜdego i całego 
kodu ASP.NET od kodu interfejsu uŜytkownika. Teraz zamiast jednego pliku z rysunku 19.1 
otrzymujemy dwa pliki przedstawione na rysunku 19.2. 

 

background image

Wył

ą

cznie kod HTML 

<%@ Page Inherits="CodeBehind2" src="CodeBehind2.vb" %> 
 
<html><body> 
   <form runat="server"> 
      <asp:Calendar id="Calendar1" runat="server" 
         OnSelectionChanged="DateChanged" 
         Cellpadding="5" Cellspacing="5" 
         DayHeaderStyle-Font-Bold="True" 
         DayNameFormat="Short" 
         Font-Name="Arial" Font-Size="12px" 
         height="250px" 
         NextPrevFormat="ShortMonth" 
         NextPrevStyle-ForeColor="white" 
         SelectedDayStyle-BackColor="#ffcc66" 
         SelectedDayStyle-Font-Bold="True" 
         SelectionMode="DayWeekMonth" 
         SelectorStyle-BackColor="#99ccff" 
         SelectorStyle-ForeColor="navy" 
         SelectorStyle-Font-Size="9px" 
         ShowTitle="true" 
         TitleStyle-BackColor="#ddaa66" 
         TitleStyle-ForeColor="white" 
         TitleStyle-Font-Bold="True" 
         TodayDayStyle-Font-Bold="True" /> 
   </form> 
   Wybrałe

ś

:  

   <asp:Label id="lblMessage" runat="server"/> 
</body></html> 

 

Wył

ą

cznie kod ASP.NET (kod obsługi formularza) 

Imports System 
Imports System.Web 
Imports System.Web.UI 
Imports System.Web.UI.WebControls 
 
Public Class CodeBehind2 : Inherits Page 
   public lblMessage as Label 
   public Calendar1 as Calendar 
    
   Public sub Page_Load(obj as object, e as eventargs) 
      if not Page.IsPostBack then 
         Calendar1.SelectedDate = DateTime.Now 
         lblMessage.Text = Calendar1.SelectedDate. _ 
            ToString("dddd, MMMM dd yyyy") 
      end if 
   End Sub 
    
   Public sub DateChanged(obj as object, e as eventargs) 
      if Calendar1.SelectedDates.Count > 1 then 
         lblMessage.Text = Calendar1.SelectedDates(0). _ 
            ToString("dddd, MMMM dd yyyy") & " do " & _ 
            Calendar1.SelectedDates(Calendar1.SelectedDates. _ 
            Count - 1).ToString("dddd, MMMM dd yyyy") 
      else 
         lblMessage.Text = Calendar1.SelectedDate. _ 
            ToString("dddd, MMMM dd yyyy") 
      end if 
   End Sub 
End Class 

 

Przeanalizujmy jeszcze raz sposób działania ASP.NET, abyśmy lepiej zrozumieli model 
programowania wykorzystujący kod obsługi. 

Gdy klient po raz pierwszy przesyła Ŝądanie dotyczące jakiejś strony ASP.NET (pliku z 
rozszerzeniem 

.aspx

), ASP.NET przetwarza tę stronę i analizuje wszystkie wykorzystywane na 

niej komponenty (na przykład, elementy sterujące serwera). Następnie ASP.NET tworzy klasę 
dynamiczną dla danego pliku 

.aspx

. To właśnie tak klasa jest następnie kompilowana, 

wykonywana i to ona generuje kod HTML przesyłany następnie do klienta. Musi to być kasa 
potomna klasy 

System.Web.UI.Page

, która zawiera definicje wykorzystywane przez wszystkie 

stron ASP.NET. Cały ten proces jest wykonywany w sposób całkowicie niezauwaŜalny, w 
momencie zgłoszenia Ŝądania dotyczącego strony ASP.NET. 

background image

Jednak plik 

.aspx

 nie musi być bezpośrednią klasą potomną klasy 

Page

 — o ile tylko w 

jakikolwiek sposób będzie dziedziczyć po tej klasie, to wszystko będzie w porządku. Oznacza to, 
Ŝ

e moŜna stworzyć pewną klasę pośrednią, dziedziczącą po klasie 

Page

 i zaŜądać, aby plik 

.aspx

 

dziedziczył po tej klasie pośredniej. Ta nowa klasa pośrednia moŜe udostępniać dowolne 
moŜliwości funkcjonalne, które będą dostępne dla plików 

.aspx

. Wzajemne relacje pomiędzy tymi 

wszystkimi klasami zostały przedstawione na rysunku 19.3. 

Ta nowa klasa  pośrednia jest naszym kodem obsługi formularzy. Definiuje ona moŜliwości 
funkcjonalne z których moŜe korzystać strona ASP.NET. Jednak przy tak duŜej ilości 
wykorzystywanych klas łatwo będzie się moŜna pogubić. W zasadzie wszystko sprowadza się do 
tego, iŜ strona ASP.NET musi być klasą potomną klasy 

Page

, lecz od programisty zaleŜy 

określenie hierarchii tego pokrewieństwa. 

Wprowadzenie klasy kodu obsługi nie daje Ŝadnych oczywistych korzyści. Strona kodu obsługi 
nie zawiera Ŝadnych własnych moŜliwości funkcjonalnych, a zatem dziedzicząc po niej strona 
ASP.NET niczego nie zyskuje. Strona kodu obsługi takŜe w Ŝaden sposób nie wspomaga 
wykonywania stron ASP.NET. Niemniej jednak wykorzystanie tej strony pozwala na przeniesienie 
kodu do klasy pośredniej, dzięki czemu w stronie ASP.NET moŜe pozostać znacznie uproszczony 
kod obsługi interfejsu uŜytkownika. 

Wykorzystanie kodu obsługi w stronach ASP.NET 

Stworzenie kodu obsługi formularza jest niezwykle proste; cały proces przypomina tworzenie 
obiektów biznesowych, z tą róŜnicą iŜ niczego nie trzeba kompilować. Niemniej jednak trzeba 
przedsięwziąć pewne środki bezpieczeństwa, aby zapewnić Ŝe wszystko będzie działać poprawnie. 
Listing 19.1 przedstawia typową postać strony ASP.NET prezentującej informacje pobierane z 
bazy danych. Za chwilę, na podstawie tej strony wygenerujemy kod obsługi formularza. 

 

Listing 19.1. 

Typowa strona ASP.NET zawiera zarówno kod programu jak i kod HTML. 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Data" %> 

3

 

<%@ Import Namespace="System.Data.OleDb" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   'deklarujemy poł

ą

czenie 

7

 

   dim strConnString as string = "Provider=" & _ 

8

 

      "Microsoft.Jet.OLEDB.4.0;" & _ 

9

 

      "Data Source=C:\ASPNET\data\banking.mdb" 

10

 

   dim objConn as new OleDbConnection(strConnString) 

11

 

    

12

 

   sub Page_Load(obj as Object, e as EventArgs)  

13

 

      if Not Page.IsPostBack then 

14

 

         FillDataGrid() 

15

 

      end if 

16

 

   end sub 

17

 

 

18

 

   private sub FillDataGrid(Optional EditIndex as integer=-1) 

19

 

      'otwieramy poł

ą

czenie 

20

 

      dim objCmd as OleDbCommand = new OleDbCommand _ 

21

 

         ("select * from tblUsers", objConn) 

22

 

      dim objReader as OleDbDataReader 

23

 

        

24

 

      try 

25

 

         objCmd.Connection.Open() 

26

 

         objReader = objCmd.ExecuteReader 

27

 

      catch ex as OleDbException 

28

 

         lblMessage.Text = "Bł

ą

d pobierania informacji z bazy danych." 

29

 

      end try 

30

 

        

31

 

      DataGrid1.DataSource = objReader 

32

 

      DataGrid1.DataBind() 

33

 

        

34

 

      objReader.Close 

35

 

      objCmd.Connection.Close() 

36

 

   end sub 

37

 

</script> 

background image

38

 

 

39

 

<html><body> 

40

 

   <form runat="server"> 

41

 

      <asp:Label id="lblMessage" runat="server" /> 

42

 

    

43

 

      <asp:DataGrid id="DataGrid1" runat="server"  

44

 

         BorderColor="black"  

45

 

         GridLines="Vertical"  

46

 

         cellpadding="4"  

47

 

         cellspacing="0"  

48

 

         width="100%" 

49

 

         Font-Name="Arial"  

50

 

         Font-Size="8pt"  

51

 

         HeaderStyle-BackColor="#cccc99" 

52

 

         ItemStyle-BackColor="#ffffff" 

53

 

         AlternatingItemStyle-Backcolor="#cccccc" 

54

 

         AutoGenerateColumns="True" /> 

55

 

      </asp:DataGrid><p> 

56

 

   </form> 

57

 

</body></html> 

 

Analiza 

Kod przedstawiony na powyŜszym listingu nawiązuje połączenie z bazą danych stworzoną w 
rozdziale 8, pt.: „Podstawowe wiadomości na temat tworzenia baz danych”. W wierszach od 7. do 
9. jest tworzony łańcuch zapytania, a w wierszu 10. obiekt 

OleDbConnection

. W procedurze 

Page_Load

 wywoływana jest procedura 

FillDataGrid

, która pobiera informacje z bazy danych 

i wiąŜe je z elementem sterujący 

DataGrid

 zdefiniowanym w wierszach od 43. do 55. Wykonanie 

powyŜszej strony powoduje wygenerowanie wyników przedstawionych na rysunku 19.4. 

 

 

Rysunek 19.4. 

Prosta strona ASP.NET pobierająca informacje z bazy danych. 

A teraz, bazując na kodzie przedstawionym na listingu 19.1, stworzymy kod obsługi formularza. 
W pierwszej kolejności naleŜy stworzyć klasę potomną klasy 

System.Web.UI.Page

. Oto 

przykład szkieletu takiej klasy: 

Imports System 
Imports System.Web 
Imports System.Web.UI 
Imports System.Web.UI.WebControls 
Imports System.Data 
Imports System.Data.OleDb 
 
Public Class CodeBehind1 : Inherits Page 
   ‘tu zostanie wstawiony kod klasy 
End Class 
 

background image

PowyŜszy szkielet klasy będzie podstawą do usunięcia kodu skryptu ze strony przedstawionej na 
listingu 19.1. NaleŜy pamiętać, Ŝe tworząc klasę języka VB.NET naleŜy własnoręcznie 
zaimportować wszystkie przestrzenie nazw, które w ASP.NET były importowane automatycznie. 
Dodatkowo trzeba takŜe zaimportować przestrzenie nazw 

System.Data

 oraz 

System.Data.OleDb

, gdyŜ tworzona strona ASP.NET będzie z nich korzystać przy 

wyświetlaniu danych.  

Kolejnym krokiem jest stworzenie wszystkich zmiennych publicznych, których będziemy 
potrzebować. Ze względu na naturę kodu obsługi formularzy, proces ten będzie się nieco róŜnić do 
tego, do czego jesteśmy przyzwyczajeni. Przyjrzyjmy się nieco dokładniej temu zagadnieniu. 
Klasa kodu obsługi będzie uŜywana do kontroli interfejsu uŜytkownika (czyli, formularza 
internetowego) — zawiera ona całą logikę konieczną do obsługi zdarzeń generowanych przez 
interfejs uŜytkownika. Jednak klasa ta nie zawiera Ŝadnych elementów interfejsu uŜytkownika — 
bez wyjątków są one umieszczane w kodzie strony 

.aspx

. A zatem mamy problem. Klasa kodu 

obsługi musi kontrolować interfejs uŜytkownika, który w całości jest definiowany w odrębnym 
pliku. W jaki sposób moŜna to zrobić? 

Zaraz poznasz powód dla którego strona ASP.NET ma być klasą potomną klasy kodu obsługi. 
OtóŜ jeśli wszystkie konieczne elementy interfejsu uŜytkownika zastaną zadeklarowane w klasie 
kodu obsługi, to plik 

.aspx

 odziedziczy je. Oznacza to, Ŝe kod obsługi stworzy i obsłuŜy wszystkie 

elementy interfejsu uŜytkownika, lecz nie będzie ich wyświetlać. Za wyświetlenie elementów 
interfejsu uŜytkownika wciąŜ będzie odpowiedzialna strona ASP.NET. PowyŜsza idea została 
zilustrowana na rysunku 19.5. 

Przenieśmy zatem kod z listingu 19.1 do kodu obsługi formularza przedstawionego na listingu 
19.2. 

 

Listing 19.2. 

Kod obsługi zawiera wszelkie moŜliwości funkcjonalne związane z obsługą 

interfejsu uŜytkownika (

CodeBehind1.vb

1

 

Imports System 

2

 

Imports System.Web 

3

 

Imports System.Web.UI 

4

 

Imports System.Web.UI.WebControls 

5

 

Imports System.Data 

6

 

Imports System.Data.OleDb 

7

 

 

8

 

Public Class CodeBehind1 : Inherits Page 

9

 

   'deklarujemy zmienne publiczne, które oddziedziczy 

10

 

   'plik .aspx. 

11

 

   public lblMessage as Label 

12

 

   public DataGrid1 as DataGrid 

13

 

    

14

 

   'deklarujemy ła

ń

cuch poł

ą

czenia 

15

 

   private strConnString as string = "Provider=" & _ 

16

 

      "Microsoft.Jet.OLEDB.4.0;" & _ 

17

 

      "Data Source=C:\ASPNET\data\banking.mdb" 

18

 

   private objConn as new OleDbConnection(strConnString) 

19

 

    

20

 

   sub Page_Load(obj as Object, e as EventArgs)  

21

 

      if Not Page.IsPostBack then 

22

 

         FillDataGrid() 

23

 

      end if 

24

 

   end sub 

25

 

 

26

 

   private sub FillDataGrid(Optional EditIndex as integer=-1) 

27

 

      'otwieramy poł

ą

czenie 

28

 

      dim objCmd as OleDbCommand = new OleDbCommand _ 

29

 

         ("select * from tblUsers", objConn) 

30

 

      dim objReader as OleDbDataReader 

31

 

        

32

 

      try 

33

 

         objCmd.Connection.Open() 

34

 

         objReader = objCmd.ExecuteReader 

35

 

      catch ex as OleDbException 

36

 

         lblMessage.Text = "Bł

ą

d przy pobieraniu danych z bazy." 

37

 

      end try 

38

 

        

39

 

      DataGrid1.DataSource = objReader 

background image

40

 

      DataGrid1.DataBind() 

41

 

        

42

 

      objReader.Close 

43

 

      objCmd.Connection.Close() 

44

 

   end sub 

45

 

     

46

 

End Class 

 

Analiza 

Zapisz powyŜszy kod w pliku o nazwie 

CodeBehind1.vb

. W wierszach od 1. do 6. są importowane 

niezbędne przestrzenie nazw, a w wierszu 8. rozpoczyna się deklaracja klasy kodu obsługi. Zwróć 
uwagę, iŜ nosi ona nazwę 

CodeBehind1

 i jest klasą potomną klasy 

Page

.  

Na stronie ASP.NET z listingu 19.1 zostały uŜyte dwa elementy sterujące serwera — etykieta o 
nazwie 

lblMessage

 oraz element 

DataGrid

  nazwie 

DataGrid1

. W naszej klasie kodu obsługi 

elementy te zostały zadeklarowane jako zmienne (odpowiednio w wierszach 10. i 11.). Teraz 
strona ASP.NET odziedziczy te elementy oraz wszelkie moŜliwości funkcjonalne zdefiniowane w 
klasie. Pozostała część kodu nie róŜni się niczym do zawartości strony z listingu 19.1; oczywiście 
nie dotyczy to kodu HTML który w pliku 

CodeBehind1.vb

 nie został umieszczony. Teraz 

przyjrzyjmy się kodowi strony 

.aspx

, która będzie dziedziczyć po klasie kodu obsługi. 

 

Listing 19.3. 

Dziedziczenie po klasie kodu obsługi. 

1

 

<%@ Page Inherits="CodeBehind1" src="CodeBehind1.vb" %> 

2

 

 

3

 

<html><body> 

4

 

   <form runat="server"> 

5

 

      <asp:Label id="lblMessage" runat="server" /> 

6

 

    

7

 

      <asp:DataGrid id="DataGrid1" runat="server"  

8

 

         BorderColor="black" GridLines="Vertical"  

9

 

         cellpadding="4" cellspacing="0"  

10

 

         width="100%" Font-Name="Arial"  

11

 

         Font-Size="8pt"  

12

 

         HeaderStyle-BackColor="#cccc99" 

13

 

         ItemStyle-BackColor="#ffffff" 

14

 

         AlternatingItemStyle-Backcolor="#cccccc" 

15

 

         AutoGenerateColumns="True" /> 

16

 

      </asp:DataGrid><p> 

17

 

   </form> 

18

 

</body></html> 

 

Analiza 

Zapisz powyŜszy fragment kodu w pliku o nazwie 

listing1903.aspx

 i umieść go w tym samym 

folderze, w którym został zapisany plik zawierający klasę kodu obsługi. Za wyjątkiem pierwszego 
wiersza powyŜszy kod niczym nie róŜni się od fragmentu kodu HTML z listingu 19.1. Jednak w 
pierwszym wierszu pojawił się nowy element — dyrektywa 

@ Page

 z atrybutami 

Inherits

 oraz 

src

. Pierwszy z tych atrybutów — 

Inherits

 — określa klasę nadrzędną, po której będzie 

dziedziczyć strona ASP.NET. W naszym przypadku chcemy, aby klasą nadrzędną strony była 
klasa kodu obsługi — 

CodeBehind1

. Atrybut 

src

 zawiera ścieŜkę dostępu do pliku kodu obsługi 

(oznacza to, iŜ plik zawierający kod obsługi oraz plik 

.aspx

 nie muszą być umieszczone w tym 

samym folderze). I to wszystko! Wystarczy wyświetlić tę stronę w przeglądarce, a uzyskane 
wyniki nie powinny się niczym róŜnić od wyników przedstawionych na rysunku 19.4. 

 

Elementy sterujące serwera 

DataGrid

 oraz 

Label

 z listingu 19.3 są kopiami zmiennych 

klasowych (klasy 

CodeBehind1

), zadeklarowanych na listingu 19.2. A zatem, dowolny kod 

umieszczony wewnątrz klasy kodu obsługi i odwołujący się do tych zmiennych, będzie miał pełen 
dostęp do wszystkich właściwości odpowiednich elementów sterujących formularza internetowego 
(takich jak tekst wyświetlany przez etykietę). 

Przyjrzyjmy się teraz kodowi obsługującemu zdarzenia generowane przez formularz. Tym razem 
oba pliki zostaną utworzone od samego początku. Listing 19.4 przedstawia kod strony ASP.NET 
definiującej interfejs uŜytkownika. 

background image

 

Notatka 
Nic  nie  stoi  na  przeszkodzi,  aby  elementy  interfejsu  u

Ŝ

ytkownika  oraz  logika  działania  strony 

ASP.NET  były  umieszczone  w  tym  samym  pliku.  Kod  programu  nie  musi  by

ć

  w  cało

ś

ci 

umieszczany  w  klasie  kodu  obsługi,  a  w  pliku  kodu  obsługi  mo

Ŝ

na  umieszcza

ć

  elementy 

interfejsu  u

Ŝ

ytkownika.  Co  wi

ę

cej,  elementy  interfejsu  u

Ŝ

ytkownika  deklarowane  w  kodzie 

obsługi, mog

ą

 by

ć

 obsługiwane przez kod zdefiniowany w pliku 

.aspx

. Niemniej jednak nie ma 

Ŝ

adnego  powodu,  aby  umieszcza

ć

  kod  w  stronie  ASP.NET  je

ś

li  mo

Ŝ

na  go  zaimplementowa

ć

 

jako kod obsługi. 

 

Listing 19.4. 

Plik 

.aspx

 bez kodu ASP.NET. 

1

 

<%@ Page Inherits="CodeBehind2" src="CodeBehind2.vb" %> 

2

 

 

3

 

<html><body> 

4

 

   <form runat="server"> 

5

 

      <asp:Calendar id="Calendar1" runat="server" 

6

 

         OnSelectionChanged="DateChanged" 

7

 

         Cellpadding="5" Cellspacing="5" 

8

 

         DayHeaderStyle-Font-Bold="True" 

9

 

         DayNameFormat="Short" 

10

 

         Font-Name="Arial" Font-Size="12px" 

11

 

         height="250px" 

12

 

         NextPrevFormat="ShortMonth" 

13

 

         NextPrevStyle-ForeColor="white" 

14

 

         SelectedDayStyle-BackColor="#ffcc66" 

15

 

         SelectedDayStyle-Font-Bold="True" 

16

 

         SelectionMode="DayWeekMonth" 

17

 

         SelectorStyle-BackColor="#99ccff" 

18

 

         SelectorStyle-ForeColor="navy" 

19

 

         SelectorStyle-Font-Size="9px" 

20

 

         ShowTitle="true" 

21

 

         TitleStyle-BackColor="#ddaa66" 

22

 

         TitleStyle-ForeColor="white" 

23

 

         TitleStyle-Font-Bold="True" 

24

 

         TodayDayStyle-Font-Bold="True" /> 

25

 

   </form> 

26

 

   Wybrałe

ś

:  

27

 

   <asp:Label id="lblMessage" runat="server"/> 

28

 

</body></html> 

 

PowyŜszy listing zawiera element sterujący serwera 

Calendar

 oraz etykietę. Choć plik kodu 

obsługi nie został jeszcze utworzony, to jednak nazwa klasy oraz ścieŜka dostępu do pliku zostały 
juŜ podane w dyrektywnie 

@ Page

 umieszczonej w pierwszym wierszu. W ten sposób juŜ 

zawczasu wiadomo jaki plik naleŜy utworzyć. W wierszu 6. określana jest procedura obsługi 
zdarzenia 

SelectionChanged

 kalendarza (elementu sterującego serwera 

Calendar

). NaleŜy 

takŜe zwrócić uwagę na nazwy obu elementów sterujących — 

Calendar1

 oraz 

lblMessage

.  

Próba wyświetlenia tej strony bez wcześniejszego utworzenia kodu obsługi, spowoduje 
wystąpienie błędów. Błędy te zostaną zgłoszone z dwóch powodów. Po pierwsze ASP.NET będzie 
szukać klasy kodu obsługi podanej w atrybucie 

Inherit

 dyrektywy 

@ Page

 lecz nie będzie w 

stanie jej znaleźć. Po drugie, do obsługi zdarzenia 

SelectionChanged

 ma być wykorzystana 

procedura 

DateChanged

, która nigdzie nie została zdefiniowana. Aby rozwiązać te problemy, 

wystarczy stworzyć kod obsługi przedstawiony na listingu 19.5. 

 

Listing 19.5. 

Kontrola zdarzeń generowanych przez element sterujący kalendarza 

(

CodeBehind2.vb

). 

1

 

Imports System 

2

 

Imports System.Web 

3

 

Imports System.Web.UI 

4

 

Imports System.Web.UI.WebControls 

5

 

 

6

 

Public Class CodeBehind2 : Inherits Page 

7

 

   public lblMessage as Label 

background image

8

 

   public Calendar1 as Calendar 

9

 

    

10

 

   Public sub Page_Load(obj as object, e as eventargs) 

11

 

      if not Page.IsPostBack then 

12

 

         Calendar1.SelectedDate = DateTime.Now 

13

 

         lblMessage.Text = Calendar1.SelectedDate. _ 

14

 

            ToString("dddd, MMMM dd yyyy") 

15

 

      end if 

16

 

   End Sub 

17

 

    

18

 

   Public sub DateChanged(obj as object, e as eventargs) 

19

 

      if Calendar1.SelectedDates.Count > 1 then 

20

 

         lblMessage.Text = Calendar1.SelectedDates(0). _ 

21

 

            ToString("dddd, MMMM dd yyyy") & " do " & _ 

22

 

            Calendar1.SelectedDates(Calendar1.SelectedDates. _ 

23

 

            Count - 1).ToString("dddd, MMMM dd yyyy") 

24

 

      else 

25

 

         lblMessage.Text = Calendar1.SelectedDate. _ 

26

 

            ToString("dddd, MMMM dd yyyy") 

27

 

      end if 

28

 

   End Sub 

29

 

End Class 

 

Analiza 

Zapisz powyŜszy fragment kodu w pliku o nazwie 

CodeBehind2.vb

. W wierszu 6. deklarowana 

jest klasa kodu obsługi o nazwie 

CodeBehind2

; co odpowiada nazwie podanej w atrybucie 

Inherit

 dyrektywy 

@ Page

 z listingu 19.4. W wierszach 7. i 8. tworzone są dwie zmienne 

publiczne — 

lblMessage

 oraz 

Calendar1

. NaleŜy zwrócić uwagę, iŜ są to te same nazwy które 

nadaliśmy elementom sterującym w pliku 

.aspx

. Procedura 

Page_Load

 zapisana w wierszach od 

10. do 16. wybiera w kalendarzu dzisiejszą datę i wyświetla stosowny komunikat wykorzystując w 
tym celu element sterujący etykiety. 

I w końcu, metoda 

DataChanged

 której kod rozpoczyna się w wierszu 18. słuŜy do obsługi 

zdarzeń 

SelectionChanged

 kalendarza (patrz wiersz 6. listingu 19.4). Metoda ta wyświetla na 

stronie datę w rozbudowanym formacie. Jeśli jednocześnie zostanie wybranych kilka dni (co 
moŜna sprawdzić za pomocą właściwości 

SelectedDates.Count

), to chcemy poinformować 

uŜytkownika o tym fakcie wyświetlając na stronie odpowiedni przedział dat (patrz wiersze od 19. 
do 23.). W przeciwnym przypadku wyświetlana jest jedna — wybrana data (patrz wiersze 25. i 
26.). Teraz wyświetlenie w przeglądarce strony z listingu 19.4 da rezultaty przedstawione na 
rysunku 19.6. 

 

 

Rysunek 19.6. 

Kod obsługi formularza obsługuje zdarzenia generowane na stronie ASP.NET 

 

background image

Teraz moŜesz juŜ całkowicie oddzielić kod obsługujący formularze internetowe od warstwy 
prezentacji danych. 

Wykorzystanie kodu obsługi w elementach 
steruj

ą

cych u

Ŝ

ytkownika 

Wykorzystanie kodu obsługi w elementach sterujących uŜytkownika róŜni się nieco od 
wykorzystania go do obsługi interfejsu uŜytkownika stron ASP.NET. Konkretnie rzecz biorąc, w 
tym przypadku, kod obsługi musi być klasą potomną klasy 

System.Web.UI.UserControl

 (a 

nie klasy 

Page

). Więcej informacji na temat tworzenia i wykorzystania elementów sterujących 

uŜytkownika moŜna znaleźć w rozdziale 6., pt.: „Ciąg dalszy wiadomości na temat tworzenia 
formularzy internetowych”. Na listingach od 19.6 do 19.8 przedstawiony został zmodyfikowany 
kod aplikacji kalkulatora stworzonej w rozdziale 2., w którym został wykorzystany element 
sterujący uŜytkownika oraz kod obsługi formularza. 

 

Listing 19.6. 

Element sterujący uŜytkownika (

Calculator.ascx

). 

1

 

<%@ Control Inherits="CalculatorControl" src="Calculator.vb" %> 

2

 

 

3

 

Liczba 1: <asp:textbox id="tbNumber1" runat="server"/><br> 

4

 

Liczba 2: <asp:textbox id="tbNumber2" runat="server"/><p> 

5

 

<asp:button id="btAdd" runat="server" Text="+"  

6

 

   OnClick="btOperator_Click" /> 

7

 

<asp:button id="btSubtract" runat="server" Text="-"  

8

 

   OnClick="btOperator_Click"/> 

9

 

<asp:button id="btMultiply" runat="server" Text="*"  

10

 

   OnClick="btOperator_Click"/> 

11

 

<asp:button id="btDivide" runat="server" Text="/"  

12

 

   OnClick="btOperator_Click"/><p> 

13

 

Wynik:  

14

 

<asp:label id="lblMessage" runat="server"/> 

 

Analiza 

Zapisz powyŜszy fragment kodu w pliku o nazwie 

Calculator.ascx

. Element sterujący 

uŜytkownika przedstawiony na powyŜszym listingu jest bardzo prosty. Zawiera on kod HTML 
wyświetlający dwa pola tekstowe w których uŜytkownicy mogą wpisywać liczby, cztery przyciski 
umoŜliwiające wykonywanie podstawowych operacji arytmetycznych oraz etykietę słuŜącą do 
wyświetlania wyników. W pierwszym wierszu powyŜszego kodu, zamiast dyrektywy 

@ Page

 

została umieszczona dyrektywa 

@ Control

, jednak składnia jej zapisu jest identyczna — takŜe w 

tym przypadku klasa kodu obsługi jest określana przy uŜyciu atrybutu 

Inherits

 a nazwa pliku w 

jaki został on zapisany — przy uŜyciu atrybutu 

src

. Koniecznie naleŜy zapamiętać nazwy 

wszystkich elementów sterujących, gdyŜ będą one konieczne przy tworzeniu kodu obsługi 
formularza. Plik kodu obsługi dla powyŜszego elementu sterującego uŜytkownika został 
przedstawiony na listingu 19.7. 

 

Listing 19.7.  

Klasa kod obsługi (

Calculator.vb

). 

1

 

Imports System 

2

 

Imports System.Web 

3

 

Imports System.Web.UI 

4

 

Imports System.Web.UI.WebControls 

5

 

 

6

 

Public Class CalculatorControl : Inherits UserControl 

7

 

   public lblMessage as Label 

8

 

   public btAdd as Button 

9

 

   public btSubtract as Button 

10

 

   public btMultiply as Button 

11

 

   public btDivide as Button 

12

 

   public tbNumber1 as TextBox 

13

 

   public tbNumber2 as TextBox 

14

 

    

15

 

   Sub btOperator_Click(obj as object, e as eventargs) 

16

 

      lblMessage.Text = Operate(CType(obj, Button).Text, _ 

background image

17

 

         tbNumber1.Text, tbNumber2.Text).ToString 

18

 

   End Sub 

19

 

    

20

 

   private function Operate(operator as string, number1 as string, 
optional number2 as string = "1") as double 

21

 

      select case operator 

22

 

         case "+" 

23

 

            Operate = CDbl(number1) + CDbl(number2) 

24

 

         case "-" 

25

 

            Operate = CDbl(number1) - CDbl(number2) 

26

 

         case "*" 

27

 

            Operate = CDbl(number1) * CDbl(number2) 

28

 

         case "/" 

29

 

            Operate = CDbl(number1) / CDbl(number2) 

30

 

      end select 

31

 

   end function 

32

 

End Class 

 

Analiza 

Zapisz powyŜszy kod w pliku o nazwie 

Calculator.vb

. MoŜliwości funkcjonalne 

zaimplementowane w tym przykładzie są znacznie bardziej skomplikowane do tych z listingu 
19.5, niemniej jednak sposób ich zapisu jest identyczny. W pierwszej kolejności, w wierszach do 
1. do 4., są importowane niezbędne przestrzenie nazw. W wierszu 6. rozpoczyna się deklaracja 
klasy 

CalculatorControl

, będącej klasą potomną klasy 

UserControl

 (a nie klasy 

Page

). 

Następnie, w wierszach od 7. do 13. zostały zadeklarowane publiczne zmienne klasowe 
odpowiadające elementom sterującym wykorzystywanym w tworzonym elemencie sterującym 
uŜytkownika.  

Gdy uŜytkownik kliknie jeden z przycisków elementu sterującego, zostanie wykonana procedura 
obsługi zdarzenia o nazwie 

btOperator_Clicked

. Procedura ta wywoła metodę 

Operate

 

pobierającą trzy argumenty — operację jaką naleŜy wykonać oraz dwa operandy. W momencie 
przesyłania Ŝądania, przycisk jaki spowodował zgłoszenie zdarzenia będzie reprezentowany przez 
zmienną 

obj

 (patrz wiersz 15.) Przyjrzyjmy się pierwszemu argumentowi wywołania metody 

Operate

 zapisanemu w wierszu 16.: 

Ctype(obj, Button).Text 
 

PowyŜsze wyraŜenie pobiera wartość właściwości 

Text

 przycisku, który spowodował zgłoszenie 

zdarzenia (na przykład, dla przycisku 

btAdd

 będzie to „+”). Jeśli tą samą czynności mielibyśmy 

wykonać w kodzie strony ASP.NET, to wystarczyłoby uŜyć wyraŜenia 

obj.Text

, niezaleŜnie od 

tego, Ŝe klasa 

Object

 nie dysponuje właściwością o nazwie 

Text

. Jednak klasy języka VB.NET 

działają inaczej niŜ strony ASP.NET. Konkretnie rzecz biorąc nie dysponują one moŜliwością 
późnego łączenia. 

 

Nowe wyraŜenie 

źne łączenie

 (ang.: late binding) oznacza, Ŝe zmienne typu 

Object

 (takie jak 

obj

) nie są 

przetwarzane aŜ do czasu wykonania programu. AŜ do tego momentu moŜna ich uŜywać do 
reprezentacji obiektów dowolnych typów. To właśnie z tego względu moŜna uŜyć wyraŜenia 

obj.Text

 pomimo faktu, iŜ klasa 

Object

 nie dysponuje właściwością o tej nazwie. ASP.NET 

zezwoli na wykorzystania wyraŜenia 

obj.Text

 gdyŜ wie, Ŝe w czasie obsługi Ŝądania zmienna 

obj

 moŜe się stać obiektem klasy 

Button

 (gdyby się jednak nie stała, to moglibyśmy mieć 

powaŜne problemy). 

Gdyby mechanizm późnego łączenia nie był wykorzystywany, to klasa 

Object

 byłaby od razu 

przetwarzana a kompilator zgłosiłby błąd zaraz po określeniu Ŝe została podjęta próba uzyskania 
dostępu do właściwości której nie ma (klasa 

Object

 nie posiada bowiem Ŝadnej właściwości o 

nazwie 

Text

). Właśnie z tego powodu naleŜy sprawić, aby kompilator VB.NET sądził Ŝe zmienna 

obj

 jest przyciskiem jeszcze zanim zostanie przesłane Ŝądanie, gdyŜ dzięki temu będzie moŜna 

wykorzystać w kodzie właściwość 

Text

. Metoda 

CType

 rzutuje jeden typ danych na inny, a 

wyraŜenie uŜyte w wierszu 16. rzutuje zmienną typu 

Object

 na zmienną typu 

Button

. MoŜe się 

wydawać, Ŝe jest to dosyć złoŜone rozwiązanie, jednak gdy stworzysz więcej stron ASP.NET i 
zdobędziesz więcej informacji na temat łączenia, wszystko stanie się znacznie prostsze.  

background image

Metoda 

Operate

 zdefiniowana w wierszach od 20. do 31. analizuje operator przekazany przez 

metodę 

btOperator_Clicked

 przy wykorzystaniu instrukcji wyboru 

select case

. W 

zaleŜności od przekazanego operatora wykonywane jest odpowiednie działanie. Jego wynik jest 
następnie zwracany do metody 

btOperator_Clikced

 i wyświetlany na stronie WWW. 

Na listingu 19.8 przedstawiony został kod wyjątkowo krótkiej strony ASP.NET która 
wykorzystuje stworzony przed chwilą element sterujący uŜytkownika. 

 

Listing 19.8. 

Strona ASP.NET wykorzystująca element sterujący uŜytkownika oraz kod 

obsługi formularza. 

1

 

<%@ Page language="VB" %> 

2

 

<%@ Register TagPrefix="ASPNETDK" TagName="Calculator" 
src="Calculator.ascx" %> 

3

 

 

4

 

<html><body> 

5

 

   <form runat="server"> 

6

 

      <ASPNETDK:Calculator id="Calc1" runat="server"/> 

7

 

   </form> 

8

 

</body></html> 

 

Analiza 

PowyŜsza strona jest wyjątkowo prosta. Zapewne pamiętasz, Ŝe element sterujący uŜytkownika 
musi zostać zarejestrowany na stronie ASP.NET. SłuŜy do tego dyrektywa 

@ Register

, opisana 

w szczegółowo w rozdziale 6., pt.: „Ciąg dalszy wiadomości na temat tworzenia formularzy 
internetowych”. Po zarejestrowaniu, elementu sterującego uŜytkownika będzie moŜna uŜywać tak 
samo, jak wszelkich innych elementów sterujących (patrz wiersz 5.). Wyświetl tę stronę w 
przeglądarce, a następnie spróbuj wpisać jakieś liczby w polach formularza i wykonać jakieś 
działania. Wyniki powinny przypominać te, przedstawione na rysunku 19.7. 

 

 

Rysunek 19.7. 

Kod obsługi formularza obsługuje zdarzenia generowane przez element sterujący 

uŜytkownika umieszczony na stronie ASP.NET 

Pliki zasobów i lokalizacja 

Udając się na wakacje zabieramy walizkę z ubraniami, przyborami toaletowymi oraz innymi 
rzeczami osobistymi. MoŜna by takŜe zabrać te wszystkie rzeczy bezpośrednio ze sobą (albo i na 
sobie) ale było by to bardzo dziwne i niewygodne (nie wspominając w ogóle o ograniczonej ilości 

background image

kieszeni!). Ta walizka jest na wakacjach przedmiotem o pierwszorzędny znaczeniu — bez niej 
nasza wycieczka stała by się koszmarem. 

ASP.NET pozwala nam na „pakowanie walizki” dla tworzonej aplikacji. Wszelkie informacje 
(takie jak zmienne, komunikaty, notatki, rysunki, itp.) moŜna zapisać w pliku zasobu. Strony 
ASP.NET bez trudu mogą następnie pobierać zasoby zgromadzone w takim pliku, gdy tylko będą 
potrzebne. 

 

Nowe wyraŜenie 

Pliki zasobów są zazwyczaj wykorzystywane do lokalizowania aplikacji. 

Lokalizowanie

 jest 

procesem polegającym na modyfikacji wyników generowanych przez aplikację tak aby były one 
zgodne z róŜnymi kulturami i językami. MoŜna tworzyć pliki zasobów dla wszystkich kultur jakie 
będą korzystać z danej aplikacji. Na przykład, w pliku zasobów moŜna zapisać wiadomość 
powitalną. Jeśli aplikację odwiedzi osoba anglojęzyczna komunikat powitalny będzie miał postać 
„Hello”, dla uŜytkowników z Francji lub innych krajów francuskojęzycznych komunikat ten 
będzie miał postać „Bonjour”. Zapisując wiadomość powitalną dla kaŜdego z języków w 
odrębnym pliku zasobów nie trzeba będzie tworzyć róŜnych stron  ASP.NET dla róŜnych języków. 
Znacznie łatwiej jest stworzyć nowy plik zasobów. 

W ASP.NET lokalizacja aplikacji oraz grupowanie zasobów jest bardzo łatwym procesem. 
Pozwala on na modyfikację wyników działania aplikacji bez konieczności wprowadzania 
jakichkolwiek zmian w kodzie, czyli stanowi jeszcze jedną formę oddzielania kodu od treści. W 
kilku kolejnych częściach niniejszego rozdziału przedstawione zostaną sposoby określania jacy 
uŜytkownicy korzystają z aplikacji, metody modyfikacji aplikacji pod ich kątem oraz zapisywania 
zasobów w plikach. 

Lokalizowanie aplikacji 

W idealnym przypadku lokalizowania aplikacji będziemy dąŜyć do automatycznego określenia 
pochodzenia korzystających z niej uŜytkowników, tak aby moŜna było wykorzystać odpowiednie 
języki oraz inne informacje kulturowe. Niestety ze względu na charakter WWW nie ma Ŝadnego 
standardowego sposobu na określenie geograficznego połoŜenia osoby odwiedzającej witrynę. 

Na szczęście jednak istniej kilka sposobów rozwiązania tego problemu. MoŜna określić główny 
język ustawiony w przeglądarce uŜytkownika. Zazwyczaj, choć oczywiście nie zawsze, ustawienie 
to określa język oraz informacje kulturowe, które najbardziej odpowiadają uŜytkownikowi 
przeglądarki; na tej podstawie będzie moŜna określić działanie aplikacji. Odstęp do tych 
informacji zapewnia obiekt 

Request.UserLanguages

, który gromadzi informacje o językach 

przekazane przez przeglądarkę i przechowuje je w formie listy posortowanej zgodnie z 
priorytetami określonymi przez uŜytkownika. Przykład kodu umoŜliwiającego określenie 
głównego języka przedstawiony została na listingu 19.9. 

 

Listing 19.9. 

Wykorzystanie obiektu 

Request

 do określenia językowych preferencji 

uŜytkownika. 

1

 

<%@Page Language="VB" %> 

2

 

<%@Import Namespace="System.Globalization" %> 

3

 

 

4

 

<script runat="server"> 

5

 

   sub Page_Load(obj as object,e as eventargs) 

6

 

      lblMessage.Text =Request.UserLanguages(0).ToString 

7

 

   end sub 

8

 

</script> 

9

 

 

10

 

<html><body> 

11

 

   Twoim głównym j

ę

zykiem jest: 

12

 

   <asp:Label id="lblMessage" runat="server"/> 

13

 

</body></html> 

 

Analiza 

background image

W wierszu 2. importowana jest zupełnie nowa przestrzeń nazw — 

System.Globalization

Zawiera ona wiele klas, które będą konieczne przy modyfikacji wyników działania aplikacji w 
zaleŜności od ustawień językowych i kulturowych. Warto zwrócić uwagę, iŜ w powyŜszym 
przykładzie nie jest uŜywany Ŝaden obiekt którejkolwiek z klas dostępnych w tej przestrzeni nazw. 
JuŜ nie długo będziemy jednak z nich korzystać! W wierszu 6. jest pobierany i wyświetlany 
główny język uŜytkownika. Właściwość 

UserLanguages

 zwraca tablicę języków wybranych 

przez uŜytkownika (określonych w przeglądarce), posortowaną według priorytetów tych języków 
(najczęściej uŜywane języki oraz ich kody zostały przedstawione w tabeli 19.1). Język główny (lub 
język o najwyŜszym priorytecie) moŜna określić przy uŜyciu wyraŜenia 

UserLanguages(0)

Wyniki wykonania strony z listingu 19.9 zostały przedstawione na rysunku 19.8. 

 

Tabela 19.1. 

Najczęściej wykorzystywane języki i ich kody. 

Język 

Kod 

Angielski (Anglia) 

en-uk 

Angielski (Australia) 

en-au 

Angielski (Kanada) 

en-ca 

Angielski (Stany Zjednoczone) 

en-us 

Arabski (Egipt) 

ar-eg 

Chiński (Hong-Kong) 

zh-hk 

Flamandzki (Belgia) 

nl-be 

Francuski (Francja) 

fr 

Hiszpańki (tradycyjny) 

es 

Hiszpański (Meksyk) 

es-mx 

Japoński 

ja 

Koreański 

ko 

Niemiecki (Niemcy) 

de 

Polski 

pl 

Portugalski (Portugalia) 

pt 

Rosyjski (Rosja) 

ru 

Włoski (Włochy) 

it 

 

 

 

background image

 

Rysunek 19.8. 

Obiekt 

Request

 moŜe posłuŜyć od określenia głównego języka wybranego w 

przeglądarce 

 

Teraz, po określeniu głównego języka moŜna na jego podstawie określić informacje kulturowe, 
które będą wykorzystywane w aplikacji ASP.NET. W tym celu posłuŜymy się obiektem klasy 

System.Globalization.CultureInfo

. Obiekty tej klasy zawierają kompletne informacje 

reprezentujące kulturę określaną przez uŜywany język. Do informacji tych, oprócz języka, naleŜy 
takŜe uŜywany kalendarz, nazwy krajów, format zapisu liczb i dat, oraz wiele innych elementów. 
Przykład wykorzystania obiektu tej klasy został przedstawiony na listingu 19.10. 

 

Listing 19.10. 

Wykorzystanie obiektu klasy 

CultureInfo

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Globalization" %> 

3

 

 

4

 

<script runat="server"> 

5

 

   sub Page_Load(obj as object, e as eventargs) 

6

 

      dim strLanguage as string = Request.UserLanguages(0).ToString 

7

 

       

8

 

      lblMessage.Text = "J

ę

zyk główny: " & _  

9

 

         strLanguage & "<br>" 

10

 

       

11

 

      dim objCulture as new CultureInfo(strLanguage) 

12

 

      lblMessage.Text += "Pełna nazwa: " & _ 

13

 

         objCulture.EnglishName & "<br>" 

14

 

      lblMessage.Text += "Nazwa rodzima: " & _ 

15

 

         objCulture.NativeName & "<br>" 

16

 

      lblMessage.Text += "Skrót: " & _ 

17

 

         objCulture.ThreeLetterISOLanguageName & "<br>" 

18

 

      lblMessage.Text += "Godzina: " & _ 

19

 

         DateTime.Now.ToString("D", objCulture) & "<br>" 

20

 

          

21

 

   end sub    

22

 

</script> 

23

 

 

24

 

<html><body> 

25

 

   <b>Informacje kulturowe o u

Ŝ

ytkowniku:</b> <p> 

26

 

   <asp:Label id="lblMessage" runat="server"/> 

27

 

</body></html> 

 

Analiza

 

PowyŜszy kod jest modyfikacją przykładu z listingu 19.9. W wierszu 2. importowana jest 
przestrzeń nazw 

System.Globalization

. W wierszach 6. i 7. pobierany jest główny język 

background image

przeglądarki uŜytkownika (w identyczny sposób jak na listingu 19.9). Język ten jest następnie 
wyświetlany w etykiecie zdefiniowanej w wierszu 26. W wierszu 12., tworzony jest nowy obiekt 
klasy 

CultureInfo

 bazujący na pobranym wcześniej języku głównym

1

. W wierszach od 13. do 

20. wyświetlane są róŜne informacje kulturowe. W celu poprawnego sformatowania daty została 
wykorzystana metoda 

ToString

 akceptująca dwa argumenty — łańcuch znaków określający 

sposób wyświetlenia daty oraz obiekt 

CultureInfo

 zawierający dodatkowe informacje 

określające postać daty. Na rysunku 19.9 zostały przedstawione wyniki wykonania powyŜszej 
strony ASP.NET w przypadku gdy głównym językiem wybranym w przeglądarce jest francuski. 

 

 

Rysunek 19.9. 

Wyniki wygenerowane przez stronę zostały dostosowane do ustawień 

kulturowych uŜytkownika i to bez wprowadzania jakichkolwiek modyfikacji w kodzie 

 

Klasa 

CultureInfo

 udostępnia więcej właściwości, które pozwalają na uzyskanie bardziej 

szczegółowych informacji na temat ustawień kulturowych. Najczęściej stosowane właściwości tej 
klasy zostały przedstawione w tabeli 19.2. 

 

Tabela 19.2. 

Właściwości klasy 

CultureInfo

Właściwość 

Opis 

Calendar 

Kalendarz uŜywany w danej kulturze (na przykład: 
gregoriański, koreański, itp.). 

CurrentCulture 

Właściwość określa informacje kulturowe ustawione na 
serwerze (a nie w przeglądarce uŜytkownika). 
Właściwość ta zwraca obiekt klasy 

CultureInfo

                                                           

1

 Jest całkiem prawdopodobne, Ŝe przy domyślnych ustawieniach przeglądarki, na przykład polskiej wersji 

Internet Explorera, powyŜszy przykład nie będzie działać poprawnie. W przeglądarce moŜe zostać 
wyświetlone komunikat o błędzie rozpoczynający się od słów: „Culture "pl" is a neutral culture....” NaleŜy 
go rozumieć w ten sposób, iŜ informacje kulturowe określone przez przeglądarkę nie są wystarczające by na 
ich podstawie moŜna było określić sposób formatowania informacji. Rozwiązanie tego problemu sprowadza 
się do określenia (w przeglądarce) bardziej szczegółowych informacji na temat wybranego języka głównego, 
na przykład zamiast języka 

Polski [pl]

, naleŜy podać język 

pl-pl

. Po wybraniu języka głównego o takiej 

postaci powyŜszy przykład będzie działać poprawnie. 

background image

Właściwość jest przeznaczona wyłącznie do odczytu. 

CurrentUICulture 

Właściwość pobiera informacje kulturowe uŜywane na 
serwerze. Jest ona uŜywana do określania ustawień 
kulturowych plików zasobów. (Patrz podrozdział 
„Zapisywanie zasobów w plikach”, w dalszej części tego 
rozdziału.) Właściwość taj jest przeznaczona wyłącznie 
do odczytu. 

DateTimeFormat 

Zwraca obiekt klasy 

DateTimeFormatInfo

 określający 

sposób formatowania daty i czasu zgodnie z bieŜącymi 
ustawieniami kulturowymi. Więcej informacji na ten 
temat moŜna znaleźć w dokumentacji .NET SDK. 

DisplayName 

Pełna nazwa kultury reprezentowanej przez dany obiekt 

CultureInfo

, w języku określonym przez interfejs 

uŜytkownika. 

EnglishName 

Pełna nazwa obiektu klasy 

CultureInfo

 w języku 

angielskim. 

Name 

To samo co właściwość 

DisplayName

, z tym iŜ ta jest 

przeznaczona wyłącznie do odczytu. 

NativeName 

Pełna nazwa obiektu klasy 

CultureInfo

 w danym 

języku. 

NumberFormat 

Właściwość określa format wyświetlania liczb (czyli 
gdzie umieszczać przecinki, punkty dziesiętne, itp.) 
Zwraca obiekt klasy 

NumberFormatInfo

ThreeLetterISOLanguageName 

Trzyliterowy kod oznaczający daną kulturę w standardzie 
ISO 3166. 

ThreeLetterWindowLanguageName 

Wersja trzyliterowego oznaczenia kultury stosowana w 
systemie Windows. 

TwoLetterISOLanguageName 

Dwuliterowy kod oznaczający daną kulturę w standardzie 
ISO 3166. 

 

Informacje kulturowe dla danej strony ASP.NET moŜna takŜe określić przy uŜyciu atrybutu 

Culture

 dyrektywy 

@ Page

. PoniŜsza dyrektywa sprawi, Ŝe na stronie zostaną wykorzystane 

ustawienia kulturowe dla języka niemieckiego: 

<%@ Page Language="VB" Culture="de" %> 
 

W tym przypadku, jeśli na stronie będą wykorzystywane obiekty związane z ustawieniami 
kulturowymi, to wykorzystają one ustawienia kulturowe podane w dyrektywie 

@ Page

 a nie 

określone przez serwer. Na przykład, w przypadku wykorzystania ustawień kulturowych dla 
języka niemieckiego, wywołanie 

DateTime.Now.ToString("D")

 spowoduje wyświetlenie 

następującej daty: 

Montag, 3. Dezember 2001 
 
 

W przypadku uŜycia ustawień kulturowych dla języka oznaczonego symbolem 

en-us

, ten sam 

fragment kodu wygeneruje wyniki: 

Monday, December 03, 2001 
 

To bardzo prosty sposób określania ustawień kulturowych jakie mają być wykorzystane na stronie, 
o ile są one z góry znane. 

 

background image

Notatka 
Wła

ś

ciwo

ść

 

CultureInfo.CurrentCulture

 jest w rzeczywisto

ś

ci „skrótem” do wła

ś

ciwo

ś

ci 

System.Threading.CurrentThread.CurrentCulture

.  Obie  te  wła

ś

ciwo

ś

ci  zwracaj

ą

 

obiekt  klasy 

CultureInfo

,  który  mo

Ŝ

e  zosta

ć

  wykorzystany  w  sposób  przedstawiony  na 

powy

Ŝ

szych  przykładach.  Ró

Ŝ

nica  pomi

ę

dzy  nimi  polega  na  tym,  i

Ŝ

  wła

ś

ciwo

ść

 

CultureInfo.CurrentCulture

  jest  przeznaczona  wył

ą

cznie  do  odczytu,  natomiast 

wła

ś

ciwo

ść

 

System.Threading.CurrentThread.CurrentCulture

  pozwala  tak

Ŝ

e  na 

zapis  informacji.  Z  tego  powodu,  je

ś

li  b

ę

dziesz  musiał  zmieni

ć

  bie

Ŝą

ce  ustawienia  kulturowe 

powiniene

ś

 posłu

Ŝ

y

ć

 si

ę

 t

ą

 drug

ą

 wła

ś

ciwo

ś

ci

ą

Kultura  jest  wła

ś

ciwo

ś

ci

ą

  aktualnie  wykonywanego  w

ą

tku  (innymi  słowy  —  aktualnie 

wykonywanego fragmentu bie

Ŝą

cej aplikacji). W przypadku okre

ś

lania ustawie

ń

 kulturowych w 

ASP.NET  s

ą

  one  okre

ś

lane  dla  całej  aplikacji.  Oznacza  to, 

Ŝ

e  te  same  informacje  kulturowe 

mo

Ŝ

na  pobra

ć

  za  po

ś

rednictwem  bie

Ŝą

cego  w

ą

tku  jak  i  z  obiektu 

CultureInfo

.  (W  dalszej 

cz

ęś

ci 

rozdziału 

zostanie 

przedstawiony 

przykład 

wykorzystania 

obiektu 

System.Threading.CurrentThread

 

Oprócz obiektu 

CultureInfo

 moŜna takŜe wykorzystać obiekt klasy 

RegionInfo

 zawierający, 

między innymi, informacje o symbolu waluty oraz o tym, czy w danym regionie jest 
wykorzystywany system metryczny. Sposób uŜycia obiektów obu tych klas jest bardzo podobny, z 
tym, Ŝe w przypadku obiektów klasy 

RegionInfo

 nie moŜna podawać języka w celu określenia 

postaci pobieranych informacji — zamiast nich wykorzystywane są skróty nazw krajów. Na 
przykład: 

US

 dla Stanów Zjednoczonych bądź 

FR

 dla Francji. Przykład wykorzystania obiektów tej 

klasy został przedstawiony na listingu 19.11. 

 

Listing 19.11. 

Wyświetlanie informacji o regionie z jakiego pochodzi uŜytkownik. 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Globalization" %> 

3

 

 

4

 

<script runat="server"> 

5

 

   sub Page_Load(obj as object, e as eventargs) 

6

 

      dim objRegion as RegionInfo 

7

 

       

8

 

      if Page.IsPostBack then 

9

 

         objRegion = new RegionInfo(btRegion.Text) 

10

 

      else 

11

 

         objRegion = RegionInfo.CurrentRegion 

12

 

      end if 

13

 

       

14

 

      lblMessage.Text = "Region: " & objRegion.Name & "<br>" 

15

 

       

16

 

      lblMessage.Text += "Pełna nazwa: " & _  

17

 

         objRegion.EnglishName & "<br>" 

18

 

      lblMessage.Text += "Waluta: " & _  

19

 

         objRegion.CurrencySymbol & "<br>" 

20

 

      lblMessage.Text += "Waluta ISO: " & _  

21

 

         objRegion.ISOCurrencySymbol & "<br>" 

22

 

      lblMessage.Text += "Skrót: " & _  

23

 

         objRegion.ThreeLetterISORegionName & "<br>" 

24

 

      lblMessage.Text += "Czy jest u

Ŝ

ywany system metryczny: " _  

25

 

         & objRegion.IsMetric 

26

 

   end sub    

27

 

</script> 

28

 

 

29

 

<html><body> 

30

 

   <form runat="server"> 

31

 

      <b>Twoje ustawienia:</b> <p> 

32

 

      <asp:Label id="lblMessage" runat="server"/><p> 

33

 

      Zmie

ń

 na (i.e. 'US', 'FR', 'JP', etc): 

34

 

      <asp:TextBox id="btRegion" runat="server" 

35

 

         AutoPostBack=true /> 

36

 

   </form> 

37

 

</body></html> 

 

background image

Analiza 

W momencie pierwszego wyświetlenia powyŜszej strony, do obiektu 

RegionInfo

 zostaną 

wczytane domyślne informacje o regionie (patrz wiersz 11.). Informacje o aktualnie wybranym 
regionie są wyświetlane w wierszach od 14. do 25., między innymi naleŜą do nich symbol i skrót 
waluty. Gdy uŜytkownik wpisze jakieś informacje w polu tekstowym zdefiniowanym w wierszach 
34. i 35. strona zostanie automatycznie wyświetlona ponownie (dzięki uŜyciu atrybutu 

AutoPostBack

 o wartości 

true

). Kod regionu podany przez uŜytkownika w polu tekstowym jest 

następnie wykorzystywany w celu stworzenia nowego obiektu 

RegionInfo

 (patrz wiersz 9.). 

Wygląd strony po wybraniu regionu o kodzie 

JP

 (czyli Japonii) został przedstawiony na rysunku 

19.10. 

 

 

Rysunek 19.10.  Na stronie zostają wyświetlone informacje o wybranym regionie 

 

Najczęściej wykorzystywane właściwości klasy 

RegionInfo

 zostały przedstawione w tabeli 19.3. 

 

Tabela 19.3. 

Właściwości klasy 

RegionInfo

Właściwość 

Opis 

CurrencySymbol 

Symbol uŜywany do oznaczania wartości monetarnych w 
danym regionie. 

CurrentRegion 

Właściwość pobiera domyślny serwer uŜywany na serwerze 
(a nie na komputerze uŜytkownika). Właściwość zwraca 
obiekt klasy 

RegionInfo

DisplayName 

Pełna nazwa regionu identyfikowanego przez obiekt 

RegionInfo

 w języku określonym przez interfejs 

uŜytkownika. 

EnglishName 

Nazwa regionu identyfikowanego przez obiekt 

RegionInfo

 

w języku angielskim. 

IsMetric 

Wartość logiczna określająca czy w danym regionie 
wykorzystywany jest system metryczny. 

ISOCurrencySymbol 

Kod ISO znaku zapisanego we właściwości 

background image

CurrencySymbol

. Na przykład, znakowi 

$

 odpowiada kod 

ISO 

USD

Name 

Zawiera te same informacje co właściwość 

CurrencySymbol

, lecz jest przeznaczona wyłącznie do 

odczytu. 

ThreeLetterISORegionName 

Trzyliterowy kod oznaczający daną kulturę w standardzie 
ISO 3166. 

ThreeLetterWindowRegionName 

Wersja trzyliterowego oznaczenia kultury stosowana w 
systemie Windows. 

TwoLetterISORegionName 

Dwuliterowy kod oznaczający daną kulturę w standardzie 
ISO 3166. 

 

Nowe wyraŜenie 

Istnieje takŜe moŜliwość określenia sposobu 

kodowania

 wyników generowanych przez strony 

ASP.NET. Kodowanie, to sposób w jaki znaki są reprezentowane przez komputer; przykładowe 
sposoby kodowania to Unicode lub ASCII. Strony ASP.NET domyślnie uŜywają kodowania 
Unicode, jednak ustawienie to moŜe się zmieniać w zaleŜności od regionu. 

Dostępne są dwa, róŜne sposoby określania sposobu kodowania wykorzystywanego w aplikacji — 
bezpośrednio na stronach ASP.NET bądź teŜ w pliku 

web.config

. Na stronach ASP.NET sposób 

kodowania określa się przy uŜyciu atrybutu 

ResponseEncoding

 dyrektywy 

@ Page

; jak na 

poniŜszym przykładzie: 

<%@ Page Language="VB" ResponseEncoding="UTF-8" %> 
 

W przypadku określania sposobu kodowania w pliku 

web.config

 naleŜy to zrobić w następujący 

sposób: 

<configuration> 
   <system.web> 
      <globalization fileEncoding="utf-8" /> 
   </system.web> 
</configuration> 
 

Jak na razie przedstawione zostały wyłącznie sposoby zmieniania informacji generowanych przez 
obiekty związane z ustawieniami kulturowymi i regionalnymi, a co ze zwykłym tekstem? Jak 
moŜna skonwertować zwyczajny tekst, tak aby korzystał z wybranych ustawień językowych? 
Niestety nie moŜna tego zrobić w Ŝaden prosty sposób — trzeba po prostu, samodzielnie 
przetłumaczyć tekst. Jeśli witryna jest odwiedzana przez osoby posługujące się róŜnymi językami, 
to zazwyczaj będzie to oznaczać konieczność stworzenia odrębnych wersji językowych kaŜdej ze 
stron. Na szczęście w ASP.NET nie trzeba się uciekać do aŜ tak drastycznych rozwiązań — moŜna 
bowiem wykorzystać pliki zasobów. 

Zapisywanie zasobów w plikach 

Pliki zasobów są uŜywane do przechowywania informacji wykorzystywanych w aplikacjach 
niezaleŜnie od ich kodu. Istnieje moŜliwość zastosowania wielu wersji pliku zasobów, dzięki 
czemu strony ASP.NET mogą prezentować róŜne informacje bez konieczności wprowadzania 
jakichkolwiek zmian w kodzie. Posługując się przykładem lokalizacji, moŜna by stworzyć wiele 
róŜnych plików zasobów, po jednym dla kaŜdego z ustawień kulturowych wykorzystywanych 
przez uŜytkowników odwiedzających witrynę. KaŜdy z tych plików zawierałby dokładnie te same 
informacje zapisane w róŜnych językach. 

Przeanalizujmy przykład prostej strony ASP.NET, której treść moŜna umieścić w pliku zasobów. 
Kod tej strony został przedstawiony na listingu 19.12. 

 

background image

Listing 19.12. 

Strona ASP.NET, która posłuŜy jako przykład wykorzystania plików zasobów. 

1

 

<%@ Page Language="VB" %> 

2

 

 

3

 

<script runat="server"> 

4

 

   sub Page_Load(obj as Object, e as EventArgs) 

5

 

      lblMessage.Text = DateTime.Now.ToString("t") 

6

 

   end sub 

7

 

</script> 

8

 

 

9

 

<html><body> 

10

 

   <b>Witamy!</b> Teraz jest: 

11

 

   <asp:Label id="lblMessage" runat="server"/><p> 

12

 

    

13

 

   Ta strona demonstruje sposób wykorzystywania plików zasobów 

14

 

   w ASP.NET.<p> 

15

 

    

16

 

   <font size=1>Nie zapomnij sprawdzi

ć

 tego w domu!</font> 

17

 

</body></html> 

 

PowyŜszy przykład jest bardzo prosty — wyświetla kilka komunikatów tekstowych o stałej treści 
oraz bieŜącą godzinę. Wyniki wykonania tej strony zostały przedstawione na rysunku 19.11. 

 

 

Rysunek 19.11.  Prosta strona ASP.NET w której moŜna wykorzystać pliki zasobów 

 

ZałóŜmy, Ŝe chcielibyśmy przetłumaczyć tę stronę na język francuski. Oczywiście moŜna by 
stworzyć nową wersję strony o tej samej postaci lecz z innymi komunikatami tekstowymi, ale po 
co utrudniać sobie Ŝycie? Znacznie lepszym rozwiązaniem będzie stworzenie dwóch plików 
zasobów. Są to zwyczajne pliki tekstowe, które moŜna utworzyć przy uŜyciu dowolnego edytora 
tekstów. W pierwszej kolejności stwórzmy polską wersję takiego pliku. W tym celu, w edytorze 
tekstowym naleŜy wpisać poniŜszy tekst: 

[strings] 
Powitanie=Witamy! 
Czas=Teraz jest: 
Tresc=Ta strona demonstruje sposób wykorzystywania plików zasobów w ASP.NET 
Stopka=<font size=1>Nie zapomnij sprawdzi

ć

 tego w domu!</font> 

 

Zapisz ten fragment tekstu w pliku o nazwie 

data.pl.txt

 (za chwilę wyjaśnię dlaczego nazwa pliku 

ma akurat taką postać). Utworzony plik zawiera jedną sekcję, w której zostały zapisane wszystkie 
wykorzystywane łańcuchy znaków. Informacje zostały zapisane w formie par nazwa-wartość: 

Powitamie=Witamy! 

background image

 

Powitanie

 jest nazwą zasobu do którego będziemy się odwoływać w kodzie strony ASP.NET, 

natomiast 

Witamy!

 jest wartością jaka zostanie wyświetlona na stronie wynikowej. PoniŜej 

przedstawiona została francuskojęzyczna wersja pliku zasobów: 

[strings] 
Powitanie=Bonjour! 
Czas=L'heure maintenent est: 
Tresc=Cette page demonstrate utiliser files de resource avec ASP.NET 
Stopka=<font size=1>N'oublie pas essayez de faire ceci chez soi!</font> 
 

PowyŜszy tekst zapisz w pliku o nazwie 

data.fr.txt

. (Tworząc oba pliki tekstowe naleŜy pamiętać, 

aby kaŜdy z łańcuchów znaków został zapisany w osobnym wierszu. Jeśli w łańcuchu znaków 
znajdą się znaki nowego wiersza, to podczas generacji właściwych plików zasobów pojawią się 
błędy.) Warto zwrócić uwagę, iŜ w obu plikach zostały uŜyte te same nazwy kluczy. Nazwy te 
muszą być identyczne, gdyŜ w przeciwnym przypadku ASP.NET nie będzie w stanie odszukać 
zasobów. 

ASP.NET nie jest jednak w stanie korzystać z plików zasobów w ich obecnej postaci. Trzeba je 
zatem skonwertować do postaci, którą ASP.NET będzie rozumieć. Do tego celu słuŜy program 
narzędziowy 

resgen.exe

 (nazywany takŜe generatorem zasobów). Program ten konwertuje 

tekstowe pliki zasobów i na ich podstawie generuje pliki z rozszerzeniem 

.resources

. A zatem, 

wyświetl okno wiersza poleceń i przejdź do folderu, w którym zapisałeś stworzone wcześniej pliki 

.txt

. Następnie wydaj poniŜsze polecenie (i nie zapomnij nacisnąć klawisza 

Enter

): 

resgen data.pl.txt 
 
resgen data.fr.txt 
 

Program powinien wyświetlić następujące wyniki: 

Read in 4 resources from 'data.pl.txt' 
Writing resource file...  Done. 
 

Po wykonaniu powyŜszych poleceń w folderze pojawią się dwa nowe pliki — 

data.pl.resources

 

oraz 

data.fr.resources

. Z tych plików moŜe juŜ korzystać zarządca zasobów ASP.NET. A zatem, 

uŜyjmy tych zasobów na stronie ASP.NET! 

Za obsługę wszystkich zasobów w ASP.NET odpowiada obiekt klasy 

System.Resources.ResourceManager

. Obiekt taki jest w stanie odnaleźć plik zasobów 

odpowiadający ustawieniom kulturowym wykorzystywanym przez uŜytkownika i pobrać zapisane 
w nim zasoby. Sposób uŜycia tego obiektu został przedstawiony na listingu 19.13. 

 

Listing 19.13. 

Pobieranie informacji z plików zasobów przy wykorzystaniu obiektu 

ResourceManager

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Globalization" %> 

3

 

<%@ Import namespace="System.Resources" %> 

4

 

<%@ Import namespace="System.Threading" %> 

5

 

 

6

 

<script runat="server"> 

7

 

   sub Page_Load(obj as object, e as eventargs) 

8

 

      dim objRM as ResourceManager 

9

 

      dim strLanguage as string = _  

10

 

         Request.UserLanguages(0).ToString 

11

 

      dim objCulture as new CultureInfo(strLanguage) 

12

 

      Thread.CurrentThread.CurrentCulture = _  

13

 

         new CultureInfo(strLanguage) 

14

 

      Thread.CurrentThread.CurrentUICulture = _  

15

 

         new CultureInfo(strLanguage) 

16

 

       

17

 

      objRM = ResourceManager. _  

18

 

              CreateFileBasedResourceManager("data", _ 

19

 

              Server.MapPath("."), Nothing) 

20

 

       

21

 

      lblGreeting.Text = objRM.GetString("Powitanie") 

22

 

      lblTime.Text = objRM.GetString("Czas") & " " & _ 

23

 

         DateTime.Now.ToString("t") 

background image

24

 

      lblBlurb.Text = objRM.GetString("Tresc") 

25

 

      lblDisclaimer.Text = objRM.GetString("Stopka") 

26

 

       

27

 

      objRM.ReleaseAllResources 

28

 

   end sub    

29

 

</script> 

30

 

 

31

 

<html><body> 

32

 

   <b><asp:Label id="lblGreeting" runat="server"/></b>  

33

 

   <asp:Label id="lblTime" runat="server"/><p> 

34

 

    

35

 

   <asp:Label id="lblBlurb" runat="server"/><p> 

36

 

    

37

 

   <asp:Label id="lblDisclaimer" runat="server"/> 

38

 

</body></html> 

 

Analiza 

W pierwszej kolejności naleŜy zwrócić uwagę na wykorzystanie dwóch dodatkowych przestrzeni 
nazw, importowanych w wierszach 3. i 4. Przestrzeń nazw 

System.Resources

 jest konieczna 

aby moŜna było korzystać z obiektu 

ResourceManager

. TakŜe przestrzeń nazw 

System.Threading

 jest niezbędna (w dalszej części rozdziału wyjaśnię dlaczego). W wierszu 8., 

w standardowy sposób, deklarowany jest nowy obiekt 

ResourceManager

. W wierszach 9. i 10. 

określany jest główny język wybrany w przeglądarce (główny język jest określany w taki sam 
sposób jak w przykładzie przedstawionym na listingu 19.9.). 

 

W wierszach do 12. do 15., na podstawie wybranego języka głównego, określane są ustawienia 
kulturowe. Pamiętasz zapewne, Ŝe informacje kulturowe moŜna podawać przy wykorzystaniu 
właściwości 

System.Threading.CurrentThread.CurrentCulture

, która pozwala na 

pobranie lub zapis obiektu klasy 

CultureInfo

 (była o tym mowa we wcześniejszej części 

rozdziału, w podrozdziale pt.: „Lokalizowanie aplikacji”). W wierszu 12. tworzony jest nowy 
obiekt klasy 

CultureInfo

 zawierający informacje kulturowe wybrane na podstawie określonego 

wcześniej głównego języka uŜywanego w przeglądarce. Wszystkie obiekty, które dysponują 
moŜliwością lokalizacji, będą teraz wykorzystywały wybrane informacje kulturowe (na przykład, 
po wybraniu informacji kulturowych dla języka angielskiego, godzina będzie wyświetlana w 
formie 10:16 PM, a nie 22:16). 

Niemniej jednak sam fakt zmiany ustawień kulturowych nie sprawi, Ŝe ASP.NET pobierze dane z 
odpowiednich plików zasobów. W tym celu, oprócz wybrania odpowiednich informacji 
kulturowych, naleŜy takŜe przypisać odpowiednią wartość właściwości 

System.Threading.CurrentThread.CurrentUICulture

 (patrz wiersze 14. i 15.). To 

właśnie na podstawie tej właściwości ASP.NET określa jaki plik zasobów naleŜy uŜyć.  

Odczytanie zasobów z pliku realizowane jest przez metodę 

CreateFileBasedResourceManager

, której wywołanie zostało zapisane w wierszach od 17. do 

19. Metoda ta wymaga podania trzech argumentów — początkowej części (prefiksu) nazwy 
plików zasobów, ścieŜki dostępu do tych plików oraz obiektu którego naleŜy uŜyć do 
przetworzenia informacji pobranych z pliku zasobów (przy czym ten trzeci argument jest 
opcjonalny). Wartość drugiego argumentu określana jest przy uŜyciu metody 

Server.MapPath

która zwraca fizyczną ścieŜkę dostępu do folderu w jakim są przechowywane pliki zasobów. 
(Więcej informacji na temat metody 

MapPath

 moŜna znaleźć w rozdziale 4., pt.: „Stosowanie 

obiektów ASP.NET w językach C# i VB.NET”, w podrozdziale „Obiekt HttpServerUtility”.) W 
naszym przypadku nie jest potrzebny Ŝaden obiekt słuŜący do przetwarzania danych pobieranych z 
pliku zasobów, a zatem jako trzeci argument wywołania metody 

CreateFileBasedResourceManager

 naleŜy przekazać wartość 

Nothing

Przypomnij sobie, Ŝe nazwy plików zasobów mają następującą postać — 

data.kultura.resources

Metoda 

CreateFileBasedResourceManager

 poszukuje plików o nazwach pasujących do 

schematu 

prefiks.kultura.resources

. A zatem, prefiks podany w wywołaniu tej metody musi 

odpowiadać początkowej części nazw plików zasobów. W naszym przypadku, w razie wybrania 
ustawień kulturowych dla języka 

pl

 (polskiego) metoda będzie poszukiwać pliku o nazwie 

data.pl.resources

, natomiast w razie wybrania ustawień kulturowych dla języka 

fr

 (francuskiego) 

background image

będzie ona poszukiwać pliku 

data.fr.resources

. Prefiks słuŜy do logicznego grupowania plików 

zasobów. 

Następnie, w wierszach do 21. do 25. wywoływana jest metoda 

GetString

 obiektu 

ResourceManager

, która pobiera pary klucz-wartość zapisane w pliku zasobów. Pobrane 

łańcuchy znaków są wyświetlane na stronie wynikowej przy uŜyciu czterech etykiet (elementów 
sterujących

 Label

), zdefiniowanych w wierszach do 32. do 35. Otwierając plik zasobów 

zarządzający nimi mechanizm blokuje dostęp do nich, dzięki czemu Ŝadne inne aplikacje nie będą 
w stanie ich zmienić. Na rysunkach 19.12 oraz 19.13 zostały przedstawione wyniki wykonania 
strony z listingu 19.13, w przypadku wyboru ustawień kulturowych dla języków 

pl-PL

 oraz 

fr-

FR

.  

 

 

Rysunek 19.12.  W przypadku wybrania ustawień kulturowych dla języka 

pl-PL

 ASP.NET 

pobiera dane z pliku zasobów 

data.pl.resources

 

 

 

Rysunek 19.13.  W przypadku wybrania ustawień kulturowych dla języka 

fr-FR

 ASP.NET 

pobiera dane z pliku zasobów 

data.fr.resources 

 

background image

Notatka 
Warto  pami

ę

ta

ć

Ŝ

e  informacje  kulturowe  mo

Ŝ

na  tak

Ŝ

e  okre

ś

li

ć

  przy  u

Ŝ

yciu  atrybut 

Culture

 

dyrektywy 

@ Page

<%@ Page Language="VB" Culture="fr-FR" %> 

Je

ś

li  jednak  zastosujesz  takie  rozwi

ą

zanie  w  ostatnim  przykładzie,  to  zasoby  nie  zostan

ą

 

pobrane  z  odpowiedniego  pliku.  Problem  polega  na  tym,  i

Ŝ

  informacje  kulturowe  s

ą

  okre

ś

lana 

na podstawie głównego j

ę

zyka u

Ŝ

ywanego w przegl

ą

darce (okre

ś

lanego w wierszu 9.), a nie na 

podstawie atrybutu dyrektywy 

@ Page

. Aby rozwi

ą

za

ć

 ten problem, wiersze do 9. do 11. listingu 

19.13 nale

Ŝ

y zast

ą

pi

ć

 nast

ę

puj

ą

cym fragmentem kodu: 

dim strLanguage as string = CultureInfo.CurrentCulture.ToString 

 

Podpowied

ź

 

Zazwyczaj w całej aplikacji powinny by

ć

 wykorzystywane te same informacje kulturowe, dlatego 

mo

Ŝ

esz  zastanowi

ć

  si

ę

  nad  wykorzystaniem  rozwi

ą

zania  polegaj

ą

cego  na  podaniu  tych 

informacji w metodzie 

Application_BeginRequest

 definiowanej w pliku 

global.asax

. W ten 

sposób  informacje  kulturowe  b

ę

d

ą

  poprawnie  ustawiane  przed  rozpocz

ę

ciem  obsługi  ka

Ŝ

dego 

Ŝą

dania odbieranego na serwerze. 

Innym  rozwi

ą

zaniem  mogłoby  by

ć

  stworzenie  obiektu 

ResourceManager

  i  zapisanie  go  jako 

zmiennej  aplikacyjnej  w  metodzie 

Application_OnStart

.  W  ten  sposób  mo

Ŝ

na  unikn

ąć

 

konieczno

ś

ci 

tworzenia 

obiektów 

ResourceManager

 

podczas 

obsługi 

ka

Ŝ

dego 

otrzymywanego 

Ŝą

dania.  Na  przykład,  do  metody 

Application_OnStart

  mo

Ŝ

na  by  doda

ć

 

poni

Ŝ

szy fragment kodu: 

Application("RM") = New ResourceManager("data", _ 
  Server.MapPath("."), Nothing) 

Powy

Ŝ

szy fragment kodu tworzy obiekt 

ResourceManager

 dost

ę

pny dla całej aplikacji. Dost

ę

do niego mo

Ŝ

na uzyska

ć

 za pomoc

ą

 wyra

Ŝ

enia 

Application("RM")

To nie jest ASP! 

DąŜenie od oddzielenia kodu od treści stron WWW i czerpania wynikających z tego korzyści nie 
jest niczym nowym w technologii ASP.NET. W rzeczywistości programiści ASP dąŜyli do tego 
celu juŜ od dłuŜszego czasu, zwłaszcza w klasycznej technologii ASP bazującej na wykorzystaniu 
bloków kodu wykonywalnego a nie bloków deklarowania kodu. Brak moŜliwości separacji kodu 
od treści sprawiał, iŜ kod ASP musiał się przeplatać ze zwyczajnym kodem HTML. To z kolei 
niezwykle utrudniało testowanie i modyfikację stron ASP, gdyŜ programiści musieli szukać 
błędów na całej stronie. Dzięki wykorzystaniu bloków deklarowania kodu problem ten niemal 
całkowicie znikną, gdyŜ cały kod jest umieszczany w jednym miejscu — na samym początku 
strony ASP.NET. 

Programiści korzystający z tradycyjnej technologii ASP musieli oddzielać kod od treści stron przy 
uŜyciu mechanizmów dołączania zawartości plików zewnętrznych (SSI). W takich dołączanych 
plikach moŜna było umieszczać całkowicie dowolny kod, w tym takŜe kod HTML, dlatego teŜ 
często w nich umieszczano fragmenty interfejsu uŜytkownika wraz z ich obsługą. Mechanizmy 
dołączania plików są wciąŜ dostępne lecz w stronach ASP.NET znacznie częściej korzysta się 
aktualnie z elementów sterujących uŜytkownika lub kodu obsługi formularzy. Oba te rozwiązania 
— zarówno elementy sterujące uŜytkownika, jak i kod obsługi formularzy — dają znacznie 
większe moŜliwości programistycznej kontroli nad tworzonym kodem niŜ technologia SSI, w 
której moŜliwości takie praktycznie nie istniały. 

Zupełnie nowym elementem ASP.NET są pliki zasobów. Programiści którzy mieli kontakt z 
językami takimi jak Visual Basic (VB) lub C++ mogli się juŜ z nimi spotkać. Pliki zasobów były 

background image

w tych językach bardzo często wykorzystywane, zresztą z tych samych powodów, dla których 
aktualnie są one dostępne takŜe w ASP.NET — głównie chodzi tu o moŜliwość oddzielania kodu 
od treści. 

W klasycznej technologii ASP nie było Ŝadnych moŜliwości oddzielenia od stron ASP informacji 
wykorzystywanych przy lokalizowaniu aplikacji. Z tego względu, bardzo często trzeba było 
tworzyć wiele wersji tej samej strony. Co więcej, wcześniejsze wersje technologii ASP nie 
pozwalały na modyfikowanie informacji kulturowych i regionalnych. 

Wszystkie te modyfikacje sprawiają, Ŝe technologia ASP.NET jest znacznie bardziej 
wszechstronna niŜ jej poprzednie wersje. Aktualnie programiści mają znacznie więcej moŜliwości 
związanych z rozmieszczaniem kodu na stronach.