Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A Windows Presentation Foundation (WPF) stílusa és templatingja olyan funkciókra hivatkozik, amelyek lehetővé teszik a fejlesztőknek és tervezőknek, hogy vizuálisan lenyűgöző effektusokat és egységes megjelenést hozzanak létre a termékükhöz. Egy alkalmazás megjelenésének testreszabásakor erős stílus- és sablonozási modellt szeretne, amely lehetővé teszi a megjelenés karbantartását és megosztását az alkalmazásokon belül és közöttük. A WPF biztosítja ezt a modellt.
A WPF-stílusmodell másik funkciója a megjelenítés és a logika elkülönítése. A tervezők csak az XAML használatával dolgozhatnak az alkalmazások megjelenésén, ugyanakkor, amikor a fejlesztők a C# vagy a Visual Basic használatával dolgoznak a programozási logikán.
Ez az áttekintés az alkalmazás stílusára és sablonozására összpontosít, és nem tárgyalja az adatkötési fogalmakat. További információ az adatkötésről: Adatkötés áttekintése.
Fontos megérteni az erőforrásokat, amelyek lehetővé teszik a stílusok és sablonok újrafelhasználását. Az erőforrásokról további információt az XAML-erőforrások áttekintésében talál.
Minta
Az áttekintésben megadott mintakód egy egyszerű fényképböngésző alkalmazáson alapul, az alábbi ábrán látható.
Ez az egyszerű fényképminta stílust és sablonozást használ a vizuálisan lenyűgöző felhasználói élmény teremtésére. A minta két TextBlock elemet és egy ListBox vezérlőelemet tartalmaz, amelyek a képek listájához vannak kötve.
A teljes mintáért lásd a Bevezetés a stílusokhoz és a sablonmintákhoz című részt.
Stílusok
A Style-t úgy tekintheti, mint egy kényelmes módot, amellyel a tulajdonságértékek egy készletét több elemre alkalmazhatja. Bármilyen olyan elemhez használhat stílust, amely a FrameworkElement-ból vagy a FrameworkContentElement-ből származik, például Window vagy Button.
A stílus deklarálása leggyakrabban erőforrásként történik egy XAML-fájl Resources
szakaszában. Mivel a stílusok erőforrások, ugyanazokat a hatókörkezelési szabályokat tartják be, amelyek az összes erőforrásra vonatkoznak. Egyszerűen fogalmazva, ahol deklarál egy stílust, az befolyásolja, hogy hol alkalmazható a stílus. Ha például az alkalmazásdefiníció XAML-fájljának gyökérelemében deklarálja a stílust, a stílus bárhol használható az alkalmazásban.
A következő XAML-kód például két stílust deklarál egy TextBlock
, az egyik automatikusan alkalmazva van az összes TextBlock
elemre, a másikra pedig kifejezetten hivatkozni kell.
<Window.Resources>
<!-- .... other resources .... -->
<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<!--A Style that extends the previous TextBlock Style with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="TitleText">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#90DDDD" />
<GradientStop Offset="1.0" Color="#5BFFFF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
Íme egy példa a fent deklarált stílusok használatára.
<StackPanel>
<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
További információ: Stílus létrehozása vezérlőelemekhez.
ControlTemplates
A WPF-ben a ControlTemplate egy vezérlő megjelenését határozza meg. A vezérlők szerkezetét és megjelenését egy új ControlTemplate definiálásával és vezérlőelemhez való hozzárendelésével módosíthatja. A sablonok sok esetben elegendő rugalmasságot biztosítanak, hogy ne kelljen saját egyéni vezérlőket írnia.
Minden vezérlőhöz tartozik egy alapértelmezett sablon a Control.Template tulajdonsághoz. A sablon összekapcsolja a vezérlő vizuális megjelenítését a vezérlő képességeivel. Mivel az XAML-ben definiál egy sablont, kód írása nélkül módosíthatja a vezérlő megjelenését. Mindegyik sablon egy adott vezérlőhöz készült, például egy Button-hoz.
Gyakran deklarál egy sablont erőforrásként egy XAML-fájl Resources
szakaszában. Mint minden erőforrás esetében, a hatókörkezelési szabályok is érvényesek.
A vezérlősablonok sokkal több szerepet játszanak, mint a stílusok. Ennek az az oka, hogy a vezérlősablon átírja a teljes vezérlő vizuális megjelenését, míg egy stílus egyszerűen alkalmazza a tulajdonságmódosításokat a meglévő vezérlőre. Mivel azonban a vezérlő sablonja a Control.Template tulajdonság beállításával van alkalmazva, stílus használatával definiálhat vagy állíthat be sablont.
A tervezők általában lehetővé teszik egy meglévő sablon másolatának létrehozását és módosítását. A Visual Studio WPF tervezőjében például válasszon egy CheckBox
vezérlőelemet, majd kattintson a jobb gombbal, és válassza Sablon szerkesztése>Másolat létrehozásalehetőséget. Ez a parancs létrehoz egy stílust, amely meghatározza a sablon.
<Style x:Key="CheckBoxStyle1" TargetType="{x:Type CheckBox}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual1}"/>
<Setter Property="Background" Value="{StaticResource OptionMark.Static.Background1}"/>
<Setter Property="BorderBrush" Value="{StaticResource OptionMark.Static.Border1}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="checkBoxBorder" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid x:Name="markGrid">
<Path x:Name="optionMark" Data="F1 M 9.97498,1.22334L 4.6983,9.09834L 4.52164,9.09834L 0,5.19331L 1.27664,3.52165L 4.255,6.08833L 8.33331,1.52588e-005L 9.97498,1.22334 Z " Fill="{StaticResource OptionMark.Static.Glyph1}" Margin="1" Opacity="0" Stretch="None"/>
<Rectangle x:Name="indeterminateMark" Fill="{StaticResource OptionMark.Static.Glyph1}" Margin="2" Opacity="0"/>
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" Grid.Column="1" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource OptionMarkFocusVisual1}"/>
<Setter Property="Padding" Value="4,-1,0,0"/>
... content removed to save space ...
A sablonok másolatának szerkesztésével megtudhatja, hogyan működnek a sablonok. Új üres sablon létrehozása helyett egyszerűbb szerkeszteni egy másolatot, és módosítani a vizualizáció néhány aspektusát.
Lásd példaként: Sablon létrehozása vezérlő.
Sablonkötés
Észrevehette, hogy az előző szakaszban definiált sablonerőforrás a TemplateBinding Markup bővítménythasználja. A TemplateBinding
egy optimalizált formája a sablonforgatókönyvekhez készült kötéseknek, amely hasonló a {Binding RelativeSource={RelativeSource TemplatedParent}}
használatával készült kötéshez.
TemplateBinding
akkor hasznos, ha a sablon egyes részeit a vezérlő tulajdonságaihoz köti. Például minden vezérlő rendelkezik egy BorderThickness tulajdonságot. Egy TemplateBinding
segítségével kezelheti, hogy a sablon mely elemére van hatással ez a vezérlőbeállítás.
ContentControl és ItemsControl
Ha egy ContentPresenter a ControlTemplate-en belül egy ContentControl-ben van deklarálva, akkor a ContentPresenter automatikusan kapcsolódik a ContentTemplate és a Content tulajdonságokhoz. Hasonlóképpen, egy ItemsPresenterControlTemplate található ItemsControl automatikusan kötődik a ItemTemplate és Items tulajdonságokhoz.
Adatsablonok
Ebben a mintaalkalmazásban van egy ListBox vezérlő, amely a fényképek listájához van kötve.
<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>
Ez a ListBox jelenleg a következőképpen néz ki.
A legtöbb vezérlő rendelkezik valamilyen tartalomtípussal, és ez a tartalom gyakran olyan adatokból származik, amelyekhez kötéssel rendelkezik. Ebben a mintában az adatsor a fényképek listája. WPF-ben a DataTemplate segítségével határozzuk meg az adatok vizuális megjelenítését. Alapvetően az határozza meg, hogy az adatok hogyan néznek ki a renderelt alkalmazásban, hogy mit teszel bele a DataTemplate-ba.
A mintaalkalmazásban minden egyéni Photo
objektum rendelkezik egy Source
típusú sztringgel, amely meghatározza a kép fájlútvonalát. A fényképobjektumok jelenleg fájlútvonalakként jelennek meg.
public class Photo
{
public Photo(string path)
{
Source = path;
}
public string Source { get; }
public override string ToString() => Source;
}
Public Class Photo
Sub New(ByVal path As String)
Source = path
End Sub
Public ReadOnly Property Source As String
Public Overrides Function ToString() As String
Return Source
End Function
End Class
Ahhoz, hogy a fényképek képekként jelenjenek meg, egy DataTemplate kell létrehoznia erőforrásként.
<Window.Resources>
<!-- .... other resources .... -->
<!--DataTemplate to display Photos as images
instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
<Border Margin="3">
<Image Source="{Binding Source}"/>
</Border>
</DataTemplate>
</Window.Resources>
Figyelje meg, hogy a DataType tulajdonság hasonló a TargetTypeStyle tulajdonságához. Ha a DataTemplate az erőforrások szakaszban található, és megadja a DataType tulajdonságot egy típushoz, de kihagy egy x:Key
-t, a DataTemplate alkalmazásra kerül, valahányszor ez a típus megjelenik. Mindig lehetősége van arra, hogy a DataTemplate-t hozzárendelje egy x:Key
-hez, majd StaticResource
-ként állítsa be olyan tulajdonságokhoz, amelyek DataTemplate típusokat vesznek fel, mint például a ItemTemplate tulajdonság vagy a ContentTemplate tulajdonság.
Lényegében a fenti példában szereplő DataTemplate meghatározza, hogy amikor van egy Photo
objektum, az Image-ként jelenik meg egy Border-on belül. Ezzel a DataTemplatemostantól így néz ki az alkalmazás.
Az adat sablon modell más funkciókat is kínál. Például, ha olyan gyűjteményadatokat jelenít meg, amelyek más gyűjteményeket tartalmaznak, mint például egy HeaderedItemsControl típus, amely Menu-et vagy TreeView-t használ, akkor ott van a HierarchicalDataTemplateis. Egy másik adat-sablonozási funkció a DataTemplateSelector, amely lehetővé teszi, hogy egyéni logika alapján egy DataTemplate-et válasszon. További információért lásd a Data Templating Overviewdokumentumot, amely részletesen tárgyalja a különböző adatsablonozási funkciókat.
Kiváltó okok
Az eseményindító beállítja a tulajdonságokat, vagy elindítja a műveleteket, például egy animációt, amikor egy tulajdonság értéke megváltozik, vagy amikor egy esemény létre van hozva.
Style, ControlTemplateés DataTemplate mind rendelkeznek Triggers
tulajdonságokkal, amelyek eseményindítókat tartalmazhatnak. Az eseményindítóknak számos típusa van.
PropertyTriggers
Az a Trigger, amely tulajdonságértékeket állít be, vagy egy tulajdonság értékén alapuló műveleteket indít el, tulajdonság-eseményindítónak nevezzük.
A tulajdonság-eseményindítók használatának bemutatásához az egyes ListBoxItem részben áttetszővé teheti, kivéve, ha ki van választva. Az alábbi stílus egy OpacityListBoxItem értékét 0.5
értékre állítja. Ha azonban a IsSelected tulajdonság true
, a Opacity1.0
értékre van állítva.
<Window.Resources>
<!-- .... other resources .... -->
<Style TargetType="ListBoxItem">
<Setter Property="Opacity" Value="0.5" />
<Setter Property="MaxHeight" Value="75" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" Value="1.0" />
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Ez a példa egy Trigger használ egy tulajdonságérték beállításához, de vegye figyelembe, hogy a Trigger osztály olyan EnterActions és ExitActions tulajdonságokkal is rendelkezik, amelyek lehetővé teszik az eseményindítók számára a műveletek végrehajtását.
Vegye észre, hogy a MaxHeightListBoxItem tulajdonsága 75
értékűre van beállítva. Az alábbi ábrán a harmadik elem a kijelölt elem.
"Eseményindítók és Történetvázlatok"
Az eseményindító másik típusa a EventTrigger, amely egy esemény előfordulása alapján indít el egy műveletkészletet. Az alábbi EventTrigger objektumok például azt határozzák meg, hogy amikor az egérmutató belép a ListBoxItem-be, a MaxHeight tulajdonság 90
értékre animálódik egy 0.2
másodperces időtartam alatt. Amikor az egér elmozdul az elemtől, a tulajdonság egy 1
másodperces időszak alatt visszatér az eredeti értékhez. Vegye figyelembe, hogy nem szükséges To értéket megadni a MouseLeave animációhoz. Ennek az az oka, hogy az animáció képes nyomon követni az eredeti értéket.
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" Value="1.0" />
</Trigger.Setters>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="MaxHeight"
To="90" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="MaxHeight" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
További információért lásd a Storyboards áttekintését.
Az alábbi ábrán az egér a harmadik elemre mutat.
MultiTriggers, DataTriggers és MultiDataTriggers
A Trigger és EventTriggermellett más típusú triggerek is léteznek. MultiTrigger lehetővé teszi a tulajdonságértékek beállítását több feltétel alapján. A DataTrigger és a MultiDataTrigger akkor használja, ha a feltétel tulajdonsága adathoz kötött.
Vizuális állapotok
A vezérlők mindig az adott állapotban vannak . Ha például az egér egy vezérlő felszíne fölé kerül, a vezérlő a MouseOver
általános állapotának tekinthető. Egy meghatározott állapot nélküli vezérlőelemet a közös Normal
állapotban lévőnek tekintünk. Az állapotok csoportokra vannak bontva, és a korábban említett állapotok az állapotcsoport CommonStates
részét képezik. A legtöbb vezérlő két állapotcsoportból áll: CommonStates
és FocusStates
. A vezérlőelemre alkalmazott egyes állapotcsoportok közül a vezérlőelemek mindig az egyes csoportok egy-egy állapotában lesznek, például CommonStates.MouseOver
és FocusStates.Unfocused
. A vezérlőelemek azonban nem lehetnek ugyanabban a csoportban két különböző állapotban, például CommonStates.Normal
és CommonStates.Disabled
. Íme egy táblázat, amely a legtöbb vezérlő által felismert és használt állapotokat tartalmazza.
Vizualizációs állapot név | VisualStateGroup név | Leírás |
---|---|---|
Normal |
CommonStates |
Az alapértelmezett állapot. |
MouseOver |
CommonStates |
Az egérmutató a vezérlő fölé van helyezve. |
Pressed |
CommonStates |
A vezérlő be van nyomva. |
Disabled |
CommonStates |
A vezérlő le van tiltva. |
Focused |
FocusStates |
A vezérlő fókuszban van. |
Unfocused |
FocusStates |
A vezérlő nincs fókuszban. |
Ha egy vezérlősablon gyökérelemén definiál egy System.Windows.VisualStateManager, animációkat indíthat el, amikor egy vezérlő egy adott állapotba lép. A VisualStateManager
deklarálja, hogy a VisualStateGroup és a VisualState mely kombinációit kell figyelni. Amikor a vezérlő figyelt állapotba kerül, a VisualStateManager
által definiált animáció elindul.
Az alábbi XAML-kód például a CommonStates.MouseOver
állapotot figyeli a backgroundElement
nevű elem kitöltőszínének animálásához. Amikor a vezérlő visszatér a CommonStates.Normal
állapotba, a rendszer visszaállítja a backgroundElement
nevű elem kitöltőszínét.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="{TemplateBinding Background}"
Duration="0:0:0.3"/>
</VisualState>
<VisualState Name="MouseOver">
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.3"/>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
További információ a storyboardokról: Storyboards Overview.
Megosztott erőforrások és témák
Egy tipikus WPF-alkalmazás több felhasználói felületi erőforrással is rendelkezhet, amelyek az alkalmazás egészére vonatkoznak. Együttesen ez az erőforráskészlet tekinthető az alkalmazás témájának. A WPF támogatást nyújt a felhasználói felület erőforrásainak témaként való csomagolásához egy erőforrás-szótár használatával, amely ResourceDictionary osztályként van beágyazva.
A WPF-témákat a WPF által bármely elem vizualizációinak testreszabására szolgáló stílus- és templatálási mechanizmussal lehet definiálni.
A WPF-témaerőforrások beágyazott erőforrás-szótárakban vannak tárolva. Ezeket az erőforrásszótárakat egy aláírt assemblybe kell beágyazni, és ez lehet ugyanaz az assembly, amelyben maga a kód található, vagy egy különálló, párhuzamos assembly. A WPF-vezérlőket tartalmazó szerelvény PresentationFramework.dllesetében a témaerőforrások egymás melletti szerelvények sorozatában találhatók.
A téma lesz az utolsó hely, ahol megkeresi az elem stílusát. A keresés általában azzal kezdődik, hogy felsétál az elemfára, és megkeres egy megfelelő erőforrást, majd megkeresi az alkalmazáserőforrás-gyűjteményt, és végül lekérdezi a rendszert. Ez lehetővé teszi az alkalmazásfejlesztők számára, hogy újradefiniálják bármely objektum stílusát a fa vagy az alkalmazás szintjén, mielőtt elérnék a témát.
Az erőforrásszótárakat egyedi fájlokként is definiálhatja, amelyek lehetővé teszik, hogy több alkalmazásban is újra felhasználhassa a témát. Felcserélhető témákat úgy is létrehozhat, hogy több erőforrásszótárat határoz meg, amelyek ugyanazokat az erőforrástípusokat biztosítják, de különböző értékeket tartalmaznak. Ezeknek a stílusoknak vagy más erőforrásoknak az alkalmazás szintjén történő újradefiniálása az ajánlott módszer egy alkalmazás testreszabásához.
Ha több erőforrást, köztük stílusokat és sablonokat szeretne megosztani az alkalmazások között, létrehozhat egy XAML-fájlt, és meghatározhat egy ResourceDictionary, amely egy shared.xaml
fájlra mutató hivatkozást tartalmaz.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
A shared.xaml
megosztása lehetővé teszi az alkalmazások vezérlőinek egységes megjelenését, mivel maga definiál egy ResourceDictionary-t, amely egy stílus- és ecseterőforrás-készletet tartalmaz.
További információ: Egyesített erőforrás-szótárak.
Ha témát hoz létre az egyéni vezérlőhöz, tekintse meg az Erőforrások definiálása témaszinten szakaszt a Vezérlő készítésének áttekintésecímű dokumentumban.
Lásd még
.NET Desktop feedback