2013. április 18., csütörtök

Wpf #9 Stílusok

Mint sokmás deklaratív nyelv, az XAML se kerülte el a stílusok létrehozásának lehetőségét. Bár használata hosszútávon felbecsülhetetlen ez nem jelenti azt, hogy kötelező. Egy Wpf program nélküle is fut, segítségével viszont szép és jól elosztott kódot lehet készíteni.

Hagyományos módszer használatával az adott elem egyes tulajdonságai direkt módon kerülnek beállításra. Több azonos tulajdonságú elem esetén ugyanazokat a beállításokat mindenhol újra jelölni kell.

Az alábbi kód 3 gombot tesz egymás mellé.
<StackPanel Orientation="Horizontal">
 <Button Content="Click" FontSize="15" Height="30"/>
 <Button Content="Click" FontSize="15" Height="30"/>
 <Button Content="Click" FontSize="15" Height="30"/>
</StackPanel>

Mindhárom nyomógomb ugyanazt a két beállítást tartalmazza. A betűméret 15  a magasság pedig 30. Amennyiben valamelyik paramétert változtatni kell, akkor mindhárom nyomógomb esetében meg kell ezt tenni. Belátható, hogy minél több helyen szerepelenek ezek a konstans értékek, annál több módosítást kell elvégezni.

Stílusok használatával az egyes tulajdonságok csoportba rendezhetőek amelyet tetszőleges számú elem elérhet. A stílusban történő változtatás az összes olyan elemet érinti, amely használja.

Az elöbbi kód stílusokkal:
<StackPanel Orientation="Horizontal">
 <StackPanel.Resources>
  <Style x:Key="MyButton">
   <Setter Property="Button.FontSize" Value="15"/>
   <Setter Property="Button.Height" Value="30"/>
  </Style>
 </StackPanel.Resources>

 <Button Content="Click" Style="{StaticResource MyButton}"/>
 <Button Content="Click" Style="{StaticResource MyButton}"/>
 <Button Content="Click" Style="{StaticResource MyButton}"/>
</StackPanel>

Az első és legfontosabb, hogy a stílusokat un. Resource-ban kell tárolni. Ez lehet egy külön resource file is. Jelen esetben a StackPanel Resource-ban található.

A stílus hatáskörét megszabja, hogy mely elem Resource-ában lett definiálva. A példában a stílus csak a stackpanel-en belül érvényes. Amennyiben az egész oldalra érvényes stílus deklarálása a cél, úgy azt a Window.Resources alatt érdemes elhelyezni.

A <Style x:Key="MyButton">  létrehoz egy stílust amelyre az x:Key attributumban megadott névvel lehet a továbbiakban hivatkozni. Minden stílus Setter elemekből épül fel. Egy Setter elem két attributummal kell, hogy rendelkezzen.
A Property, amely meghatározza, hogy mely tulajdonság értéket kell beállítani.
A Value, amely magát az értéket tartalmazza.

A stílusra az elem Style attributumán keresztül lehet hivatkozni: 
Style="{StaticResource MyButton}".

Stílusok öröklése

Számos esetben előfordulhat, hogy egy stílus mindössze egy-két tulajdonságában tér el, egy már létező stílustól. Esetleg egy már létező stílust kell kibővíteni. Erre szolgál az öröklés lehetősége.

<StackPanel Orientation="Horizontal">
 <StackPanel.Resources>
  <Style x:Key="MyButton">
   <Setter Property="Button.FontSize" Value="15"/>
   <Setter Property="Button.Height" Value="30"/>
  </Style>
  
  <Style x:Key="MyBoldButton" BasedOn="{StaticResource MyButton}">
   <Setter Property="Button.FontWeight" Value="Bold"/>
  </Style>
 </StackPanel.Resources>

 <Button Content="Click" Style="{StaticResource MyButton}"/>
 <Button Content="Click" Style="{StaticResource MyBoldButton}"/>
 <Button Content="Click" Style="{StaticResource MyButton}"/>
</StackPanel>

Az újonnan létrehozott stílus egyfelől örökli a szülő minden beállítását (BasedOn="{StaticResource MyButton}"), másfelől kiegészíti az egy új beállítással, amely a szöveg vastagságát bold-ra állítja.

A három nyomógomb közül, a középső ezt az új stílust használja. Minden egyéb beállításban egyezik a másik kettővel, kivéve a betűvastagságot.

A Stílus elem megadása

Amennyiben egy stílusról ismert, hogy csak egyféle elem típushoz tartozik, akkor célszerű azt a stílus létrehozásakor jelölni. Az előbbi esetekben a stílusok mind nyomógombok megjelenítéséhez készültek, ezért a Property beállításnál szükség volt egy Button prefixre. Ha már a stílus deklarálásakor jelezzük, hogy az adott stílus mely típusú elemhez tartozik, akkor a prefix elhagyható.

<StackPanel Orientation="Horizontal">
 <StackPanel.Resources>
  <Style x:Key="MyStyle" TargetType="{x:Type Button}">
   <Setter Property="FontSize" Value="15"/>
   <Setter Property="Height" Value="30"/>
   <Setter Property="Background" Value="Yellow"/>
  </Style>
 </StackPanel.Resources>

 <Button Content="Click" Style="{StaticResource MyStyle}"/>
 <Button Content="Click" Style="{StaticResource MyStyle}"/>
</StackPanel>

A TargetType="{x:Type Button}" attributum használtával egyértelműen jelzésre került, hogy az adott stílus csak Button-hoz kapcsolható. Amennyiben valami más elem szeretné használni, akkor futásidejű hiba keletkezik.
Mivel a TargetType egyértelműen megadja annak az elemnek a típusát, amely az adott stílust fel fogja használni, ezért a Setter elem Property attributumában már nem kell külön Button prefixet használni.
<Setter Property="FontSize" Value="15"/>

Stílus név nélkül.

Abban az esetben, amennyiben ismert, hogy egy adott elem mindig ugyanúgy néz ki célszerű implicit stílusokat használni.

<StackPanel Orientation="Horizontal">
 <StackPanel.Resources>
  <Style TargetType="{x:Type Button}">
   <Setter Property="FontSize" Value="15"/>
   <Setter Property="Height" Value="30"/>
   <Setter Property="Background" Value="Yellow"/>
  </Style>
 </StackPanel.Resources>

 <Button Content="Click"/>
 <Button Content="Click"/>
</StackPanel>

Ebben az esetben a a Style nem tartlamaz x:Key attributumot, a TargetType megadása viszont kötelező. Hatására a StackPanelen található összes Button megkapja ezt a stílust. Használatával a Button elemnek nem kell külön jelezni, hogy melyik stílust kell használnia.

Noha egy-egy tulajdonság beállítása miatt a stílus használata eléggé felesleges többletgépelésnek látszik, a végső kódban célszerű a direkt értékadásokat megszüntetni.  A stílusok általában külön Resource file-ban kerülnek tárolásra, nem pedig az adott elemen belül
Ehhez egy új Resource Dictionary-t kell a projekthez adni, amely üresen így néz ki

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
</ResourceDictionary>

Minden stílus deklarációt ezen belül kell elhelyezni.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style x:Key="MyStyle" TargetType="{x:Type Button}">
        <Setter Property="FontSize" Value="15"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="Background" Value="Yellow"/>
    </Style>

</ResourceDictionary>

Legvégül a XAML kódban csak a Resource File-ra kell hivatkozni.

<StackPanel Orientation="Horizontal">
 <StackPanel.Resources>
  <ResourceDictionary Source="Dictionary1.xaml"/>
 </StackPanel.Resources>

 <Button Content="Click" Style="{StaticResource MyStyle}"/>
 <Button Content="Click" Style="{StaticResource MyStyle}"/>
</StackPanel>

Magát a hivatkozást szintén az adott elem Resource  tulajdonságában kell elhelyezni. Azonban itt már csak egy hivatkozás kell a külső file nevére.

A stílusok megfontolt használatával a leíró kód rövidebbé és átláthatóbbá válik, hosszútávon rengeteg felesleges és redundáns adat begépelése kerülhető el vele.

Nincsenek megjegyzések:

Megjegyzés küldése