Stiller ve şablonlar nedir? (WPF .NET)
Windows Presentation Foundation (WPF) stil oluşturma ve şablon oluşturma, geliştiricilerin ve tasarımcıların ürünleri için görsel olarak cazip efektler ve tutarlı bir görünüm oluşturmasına olanak sağlayan bir özellik paketine başvurur. Bir uygulamanın görünümünü özelleştirirken, uygulamalar içinde ve uygulamalar arasında görünümün bakımını ve paylaşımını sağlayan güçlü bir stil ve şablon oluşturma modeli istiyorsunuz. WPF bu modeli sağlar.
WPF stil modelinin bir diğer özelliği de sunu ve mantığın ayrılmasıdır. Tasarımcılar, geliştiricilerin C# veya Visual Basic kullanarak programlama mantığı üzerinde çalıştığı aynı anda yalnızca XAML kullanarak bir uygulamanın görünümü üzerinde çalışabilir.
Bu genel bakış, uygulamanın stil ve şablon oluşturma yönlerine odaklanır ve veri bağlama kavramlarını tartışmaz. Veri bağlama hakkında bilgi için bkz . Veri Bağlamaya Genel Bakış.
Stillerin ve şablonların yeniden kullanılmasını sağlayan kaynakları anlamak önemlidir. Kaynaklar hakkında daha fazla bilgi için bkz . XAML kaynaklarına genel bakış.
Örnek
Bu genel bakışta sağlanan örnek kod, aşağıdaki çizimde gösterilen basit bir fotoğraf tarama uygulamasını temel alır.
Bu basit fotoğraf örneği, görsel olarak ilgi çekici bir kullanıcı deneyimi oluşturmak için stil ve şablon oluşturmayı kullanır. Örnekte iki TextBlock öğe ve görüntü ListBox listesine bağlı bir denetim vardır.
Örneğin tamamı için bkz . Stil Oluşturma ve Şablon Oluşturma Örneğine Giriş.
Stiller
bir Style özelliğini, birden çok öğeye bir özellik değerleri kümesi uygulamak için kullanışlı bir yol olarak düşünebilirsiniz. veya gibi Window bir öğesinden FrameworkElement FrameworkContentElement türetilen herhangi bir Buttonöğede stil kullanabilirsiniz.
Stil bildirmenin en yaygın yolu, XAML dosyasının Resources
bölümündeki bir kaynaktır. Stiller kaynak olduğundan, tüm kaynaklar için geçerli olan aynı kapsam kurallarına uyarlar. Basitçe ifade edin, bir stili bildirdiğiniz yer, stilin uygulanabileceği yeri etkiler. Örneğin, stili uygulama tanımı XAML dosyanızın kök öğesinde bildirirseniz, stil uygulamanızın herhangi bir yerinde kullanılabilir.
Örneğin, aşağıdaki XAML kodu için TextBlock
biri tüm TextBlock
öğelere otomatik olarak uygulanan ve diğeri açıkça başvurulması gereken iki stil bildirir.
<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>
Yukarıda kullanılmakta olduğu bildirilen stillerin bir örneği aşağıda verilmiştir.
<StackPanel>
<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
Daha fazla bilgi için bkz . Denetim için stil oluşturma.
ControlTemplates
WPF'de, ControlTemplate denetimin görünümü denetimin görünümünü tanımlar. Yeni ControlTemplate bir tanımlayıp bir denetime atayarak denetimin yapısını ve görünümünü değiştirebilirsiniz. Çoğu durumda şablonlar, kendi özel denetimlerinizi yazmanız gerekmeyecek kadar esneklik sağlar.
Her denetimin Control.Template özelliğine atanmış varsayılan bir şablonu vardır. Şablon, denetimin görsel sunumunu denetimin özelliklerine bağlar. XAML'de şablon tanımladığınızdan, herhangi bir kod yazmadan denetimin görünümünü değiştirebilirsiniz. Her şablon, gibi Buttonbelirli bir denetim için tasarlanmıştır.
Genellikle bir şablonu XAML dosyasının Resources
bölümünde kaynak olarak bildirirsiniz. Tüm kaynaklarda olduğu gibi kapsam belirleme kuralları da geçerlidir.
Denetim şablonları bir stilden çok daha karmaşıktır. Bunun nedeni, denetim şablonunun denetimin tamamının görsel görünümünü yeniden yazması, stilin ise var olan denetime özellik değişikliklerini uygulamasıdır. Ancak, denetimin şablonu Control.Template özelliği ayarlanarak uygulandığından, şablon tanımlamak veya ayarlamak için bir stil kullanabilirsiniz.
Tasarımcılar genellikle var olan bir şablonun kopyasını oluşturmanıza ve değiştirmenize olanak sağlar. Örneğin, Visual Studio WPF tasarımcısında bir CheckBox
denetim seçin ve sağ tıklayıp Şablonu>düzenle Kopya oluştur'u seçin. Bu komut, şablonu tanımlayan bir stil oluşturur.
<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 ...
Şablonun bir kopyasını düzenlemek, şablonların nasıl çalıştığını öğrenmenin harika bir yoludur. Yeni boş bir şablon oluşturmak yerine, bir kopyayı düzenlemek ve görsel sununun birkaç yönünü değiştirmek daha kolaydır.
Örnek için bkz . Denetim için şablon oluşturma.
TemplateBinding
Önceki bölümde tanımlanan şablon kaynağının TemplateBinding İşaretlemeyi Uzantısını kullandığını fark etmiş olabilirsiniz. , TemplateBinding
ile yapılan bağlamaya benzer şekilde şablon senaryoları için en iyi duruma getirilmiş bir bağlama biçimidir {Binding RelativeSource={RelativeSource TemplatedParent}}
. TemplateBinding
, şablonun bölümlerini denetimin özelliklerine bağlamak için kullanışlıdır. Örneğin, her denetimin bir BorderThickness özelliği vardır. Şablondaki hangi öğenin bu denetim ayarından etkilendiğini yönetmek için bir TemplateBinding
kullanın.
ContentControl ve ItemsControl
içinde bir ContentPresenter bildirilirseContentControlControlTemplate, ContentPresenter ve Content özelliklerine ContentTemplate otomatik olarak bağlanır. Benzer şekilde, ItemsPresenter içinde olan bir ItemsControl ve özelliklerine Items ItemTemplate ControlTemplate otomatik olarak bağlanır.
DataTemplates
Bu örnek uygulamada, fotoğraf listesine bağlı bir denetim vardır ListBox .
<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>
Bu ListBox , şu anda aşağıdaki gibi görünür.
Denetimlerin çoğu bir tür içeriğe sahiptir ve bu içerik genellikle bağlandığınız verilerden gelir. Bu örnekte veriler fotoğrafların listesidir. WPF'de, verilerin görsel gösterimini tanımlamak için bir DataTemplate kullanırsınız. Temel olarak, içine yerleştirdiğiniz DataTemplate veriler işlenen uygulamada nasıl görüneceğini belirler.
Örnek uygulamamızda her özel Photo
nesnenin, görüntünün dosya yolunu belirten dize türünde bir Source
özelliği vardır. Şu anda fotoğraf nesneleri dosya yolları olarak görünür.
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
Fotoğrafların görüntü olarak görünmesi için kaynak olarak bir DataTemplate oluşturursunuz.
<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>
özelliğinin DataType özelliğine TargetType Stylebenzer olduğuna dikkat edin. kaynağınız DataTemplate kaynaklar bölümündeyse, özelliğini bir türe belirttiğinizde DataType ve atladığınızda x:Key
, DataTemplate bu tür her görüntülendiğinde uygulanır. her zaman öğesini ile atama DataTemplate ve ardından özellik veya özellik gibi ItemTemplate türleri alan DataTemplate özellikler için olarak StaticResource
ayarlama seçeneğiniz ContentTemplate x:Key
vardır.
Temelde, DataTemplate yukarıdaki örnekte, bir Photo
nesne olduğunda içinde olarak Image Bordergörünmesi gerektiğini tanımlar. bu DataTemplateile, uygulamamız artık şöyle görünür.
Veri şablon oluşturma modeli diğer özellikleri sağlar. Örneğin, veya TreeViewHierarchicalDataTemplategibi Menu bir HeaderedItemsControl tür kullanarak diğer koleksiyonları içeren koleksiyon verilerini görüntülüyorsanız, vardır. Başka bir veri şablon oluşturma özelliği, özel mantığa göre kullanmak üzere bir DataTemplate seçmenize olanak tanıyan özelliğidirDataTemplateSelector. Daha fazla bilgi için bkz . Farklı veri şablon oluşturma özellikleri hakkında daha ayrıntılı bir tartışma sağlayan Veri Şablonuna Genel Bakış.
Tetikleyiciler
Tetikleyici özellikleri ayarlar veya bir özellik değeri değiştiğinde veya bir olay tetiklendiğinde animasyon gibi eylemleri başlatır. Style, ControlTemplateve DataTemplate tümünün tetikleyici Triggers
kümesi içerebilen bir özelliği vardır. Birkaç tetikleyici türü vardır.
PropertyTriggers
Trigger Özellik değerlerini ayarlayan veya bir özelliğin değerine göre eylemler başlatan bir özellik tetikleyicisi olarak adlandırılır.
Özellik tetikleyicilerinin nasıl kullanılacağını göstermek için, seçilmediği sürece her ListBoxItem birinin kısmen saydam olmasını sağlayabilirsiniz. Aşağıdaki stil, değerini ListBoxItem olarak 0.5
ayarlarOpacity. IsSelected Ancak özelliği olduğundatrue
, Opacity olarak ayarlanır1.0
.
<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>
Bu örnekte bir özellik değeri ayarlamak için bir Trigger kullanılır, ancak sınıfın Trigger eylemleri gerçekleştirmek için tetikleyiciyi etkinleştiren ve ExitActions özelliklerine de sahip EnterActions olduğunu unutmayın.
özelliğinin MaxHeight olarak ayarlandığına ListBoxItem 75
dikkat edin. Aşağıdaki çizimde, üçüncü öğe seçili öğedir.
EventTriggers ve Görsel Taslaklar
Başka bir tetikleyici türü, EventTriggerbir olayın oluşumuna göre bir eylem kümesi başlatan türüdür. Örneğin, aşağıdaki EventTrigger nesneler fare işaretçisi içine girdiğinde ListBoxItemözelliğinin ikinci bir sürenin MaxHeight üzerindeki 0.2
bir değere 90
animasyon ekleneceğini belirtir. Fare öğeden uzaklaştığında, özellik saniyelik bir süre 1
boyunca özgün değere döner. Animasyon için bir To değer belirtmenin MouseLeave gerekli olmadığını unutmayın. Bunun nedeni, animasyonun özgün değeri izleyebilebilmesidir.
<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>
Daha fazla bilgi için bkz . Görsel Taslaklara genel bakış.
Aşağıdaki çizimde fare üçüncü öğeyi işaret ediyor.
MultiTriggers, DataTriggers ve MultiDataTriggers
ve'e Trigger EventTriggerek olarak, başka tetikleyici türleri de vardır. MultiTrigger özellik değerlerini birden çok koşula göre ayarlamanıza olanak tanır. ve koşulunuzun özelliği veriye bağlı olduğunda kullanırsınız DataTrigger MultiDataTrigger .
Görsel Durumlar
Denetimler her zaman belirli bir durumdadır. Örneğin, fare bir denetimin yüzeyinin üzerinde hareket ettiğinde, denetimin ortak durumunda MouseOver
olduğu kabul edilir. Belirli bir durumu olmayan bir denetimin ortak Normal
durumda olduğu kabul edilir. Durumlar gruplara ayrılır ve daha önce bahsedilen durumlar durum grubunun CommonStates
bir parçasıdır. Çoğu denetimin iki durum grubu vardır: CommonStates
ve FocusStates
. Denetime uygulanan her durum grubunda, bir denetim her zaman ve FocusStates.Unfocused
gibi CommonStates.MouseOver
her grubun tek bir durumundadır. Ancak, bir denetim ve CommonStates.Disabled
gibi CommonStates.Normal
aynı grup içinde iki farklı durumda olamaz. Çoğu denetimin tanıdığı ve kullandığı durumlardan oluşan bir tablo aşağıdadır.
VisualState Adı | VisualStateGroup Adı | Açıklama |
---|---|---|
Normal |
CommonStates |
Varsayılan durum. |
MouseOver |
CommonStates |
Fare işaretçisi denetimin üzerine yerleştirilir. |
Pressed |
CommonStates |
Denetime basılır. |
Disabled |
CommonStates |
Denetim devre dışı bırakıldı. |
Focused |
FocusStates |
Denetimin odağı vardır. |
Unfocused |
FocusStates |
Denetimin odağı yok. |
Denetim şablonunun kök öğesinde bir System.Windows.VisualStateManager tanımlayarak, bir denetim belirli bir duruma girdiğinde animasyonları tetikleyebilirsiniz. , VisualStateManager
hangi ve VisualState birleşimlerinin izleyebileceğinizi VisualStateGroup bildirir. Denetim izlenen bir duruma girdiğinde, tarafından VisualStateManager
tanımlanan animasyon başlatılır.
Örneğin, aşağıdaki XAML kodu adlı backgroundElement
öğenin dolgu rengine animasyon eklemek için durumunu izlerCommonStates.MouseOver
. Denetim duruma döndüğünde CommonStates.Normal
adlı backgroundElement
öğenin dolgu rengi geri yüklenir.
<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>
...
Görsel taslaklar hakkında daha fazla bilgi için bkz . Görsel Taslaklara Genel Bakış.
Paylaşılan kaynaklar ve temalar
Tipik bir WPF uygulamasının uygulama genelinde uygulanan birden çok kullanıcı arabirimi kaynağı olabilir. Toplu olarak, bu kaynak kümesi uygulamanın teması olarak kabul edilebilir. WPF, sınıf olarak kapsüllenmiş bir kaynak sözlüğü kullanarak ui kaynaklarını tema olarak paketleme desteği ResourceDictionary sağlar.
WPF temaları, WPF'nin herhangi bir öğenin görsellerini özelleştirmek için kullanıma sunduğu stil ve şablon oluşturma mekanizması kullanılarak tanımlanır.
WPF tema kaynakları ekli kaynak sözlüklerinde depolanır. Bu kaynak sözlükleri imzalı bir derlemeye eklenmelidir ve kodun kendisiyle aynı derlemeye veya yan yana bir derlemeye eklenebilir. PresentationFramework.dll için WPF denetimlerini içeren derleme, tema kaynakları yan yana derlemeler serisinde yer alır.
Tema, bir öğenin stilini ararken bakılması gereken son yer olur. Genellikle arama, öğe ağacına gidip uygun bir kaynağı arayarak başlar, ardından uygulama kaynak koleksiyonuna bakar ve son olarak sistemi sorgular. Bu, uygulama geliştiricilerine temaya ulaşmadan önce ağaç veya uygulama düzeyindeki herhangi bir nesnenin stilini yeniden tanımlama şansı verir.
Kaynak sözlüklerini, bir temayı birden çok uygulamada yeniden kullanmanıza olanak tanıyan tek tek dosyalar olarak tanımlayabilirsiniz. Aynı kaynak türlerini ancak farklı değerleri sağlayan birden çok kaynak sözlük tanımlayarak değiştirilebilir temalar da oluşturabilirsiniz. Bu stillerin veya diğer kaynakların uygulama düzeyinde yeniden tanımlanması, bir uygulamanın dış görünümünün belirlenmesi için önerilen yaklaşımdır.
Stiller ve şablonlar da dahil olmak üzere bir dizi kaynağı uygulamalar arasında paylaşmak için bir XAML dosyası oluşturabilir ve dosya başvurusu içeren bir shared.xaml
dosya tanımlayabilirsinizResourceDictionary.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>
Bir uygulamadaki denetimlerin shared.xaml
tutarlı bir ResourceDictionary görünüme sahip olmasını sağlayan, stil ve fırça kaynakları kümesi içeren bir öğesini tanımlayan paylaşımıdır.
Daha fazla bilgi için bkz . Birleştirilmiş kaynak sözlükleri.
Özel denetiminiz için bir tema oluşturuyorsanız, Denetim yazma genel bakışının Tema düzeyinde kaynakları tanımlama bölümüne bakın.
Ayrıca bkz.
.NET Desktop feedback