Aracılığıyla paylaş


Stiller ve şablonlar nedir?

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ı temel alır.

StilLi ListView

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 öğesi ve görüntü listesine bağlı bir ListBox denetimi vardır.

Örneğin tamamı için bkz. Stil Oluşturma ve Şablon Oluşturma Örneğine Giriş.

Stil

Bir Style, birden çok öğeye özellik değerleri kümesi uygulamak için kullanışlı bir yol olarak düşünebilirsiniz. FrameworkElement veya FrameworkContentElement'den türetilen ve Window veya Buttongibi olan herhangi bir öğede stil kullanabilirsiniz.

Stil bildirmenin en yaygın yolu, XAML dosyasının Resources bölümünde yer alan bir kaynaktır. Stiller kaynaklar olduğundan, tüm kaynaklar için geçerli olan aynı kapsama 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, bir TextBlockiçin iki stil bildirir: biri otomatik olarak tüm TextBlock öğelerine uygulanır, diğeri ise açıkça belirtilmesi gereken bir stildir.

<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>

Stilli metin blokları

Daha fazla bilgi için bkz . Denetim için stil oluşturma.

ControlTemplates

WPF'de, denetimin ControlTemplate denetimin görünümünü tanımlar. Yeni bir ControlTemplate 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, Buttongibi belirli bir denetim için tasarlanmıştır.

Genellikle XAML dosyasının Resources bölümünde bir şablonu 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 denetimi seçin ve sağ tıklayıp şablonu düzenle >bir kopya oluştur'u seçin. Bu komut, stilinin birşablonu tanımlamasını sağlar.

<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. , denetimiçin bir şablon oluşturma.

ŞablonBağlama

Önceki bölümde tanımlanan şablon kaynağının TemplateBinding İşaretleme Uzantısıkullandığını fark etmiş olabilirsiniz. TemplateBinding, {Binding RelativeSource={RelativeSource TemplatedParent}}ile yapılan bağlamaya benzer şekilde şablon senaryoları için iyileştirilmiş bir bağlama biçimidir. 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

ContentPresenter, ControlTemplate'nin ContentControl'inde bildirilirse, ContentPresenter, ContentTemplate ve Content özelliklerine otomatik olarak bağlanır. Benzer şekilde, bir ItemsPresenter, bir ControlTemplate'nin içindeki ItemsControl'de olan, otomatik olarak ItemTemplate ve Items özelliklerine bağlanır.

Veri Şablonları

Bu örnek uygulamada, fotoğraf listesine bağlı bir ListBox denetimi vardır.

<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.

Şablon uygulamadan önce ListBox

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, bir DataTemplate içine koyduğunuz veriler, uygulamanın render edildiğinde nasıl görüneceğini belirler.

Örnek uygulamamızda her özel Photo nesnesinin, görüntünün dosya yolunu belirten tür dizesinin 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>

DataType özelliğinin TargetTypeStyle özelliğine benzer olduğuna dikkat edin. DataTemplate kaynaklar bölümündeyse, bir türe DataType özelliğini belirttiğinizde ve bir x:Key'yi atladığınızda, bu tür her görüldüğünde DataTemplate uygulanır. Her zaman DataTemplate'ı bir x:Key olarak atayıp ve ardından StaticResource olarak ayarlama seçeneğine sahipsiniz; bu, DataTemplate özelliği veya ItemTemplate özelliği gibi ContentTemplate türleri alan özellikler için geçerlidir.

Temel olarak, yukarıdaki örnekteki DataTemplate, bir Photo nesnesi olduğunda, bir Imageiçinde Border olarak görünmesi gerektiğini tanımlar. Bu DataTemplateile uygulamamız artık şöyle görünür.

Fotoğraf resmi

Veri şablon oluşturma modeli diğer özellikleri sağlar. Örneğin, HeaderedItemsControl veya Menugibi bir TreeView türü kullanarak diğer koleksiyonları içeren koleksiyon verilerini görüntülüyorsanız, bu durumda HierarchicalDataTemplatede mevcuttur. Başka bir veri şablon oluşturma özelliği, özel mantığa göre kullanılacak bir DataTemplateSelector seçmenize olanak tanıyan DataTemplateözelliğidir. Daha fazla bilgi için farklı veri şablon oluşturma özellikleri hakkında daha ayrıntılı bir tartışma sağlayanVeri Şablonuna Genel Bakış bölümüne bakın.

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'nin hepsinin tetikleyici kümesi içerebilen bir Triggers özelliği vardır. Birkaç tetikleyici türü vardır.

Özellik Tetikleyicileri

Özellik değerlerini ayarlayan veya bir özelliğin değerine göre eylemler başlatan bir Trigger ö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 kısmen saydam hale getirebilirsiniz. Aşağıdaki stil, bir Opacity'in ListBoxItem değerini 0.5olarak ayarlar. Ancak IsSelected özelliği trueolduğunda, Opacity1.0olarak ayarlanır.

<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 özellik değeri ayarlamak için bir Trigger kullanılır, ancak Trigger sınıfının tetikleyicinin eylem gerçekleştirmesini sağlayan EnterActions ve ExitActions özelliklerine de sahip olduğunu unutmayın.

MaxHeight'in ListBoxItem özelliğinin 75olarak ayarlandığına dikkat edin. Aşağıdaki çizimde, üçüncü öğe seçili öğedir.

StilLi ListView

EventTriggers ve Storyboard'lar

Başka bir tetikleyici türü, bir olayın oluşumuna göre bir dizi eylem başlatan EventTrigger' dir. Örneğin, aşağıdaki EventTrigger nesneleri, fare işaretçisi ListBoxItemüzerine geldiğinde, MaxHeight özelliğinin 90 saniye süresince 0.2 değerine animasyonla ulaşacağını belirtir. Fare öğeden uzaklaştığında, özellik 1 saniyelik bir süre boyunca özgün değere döner. To animasyonu için MouseLeave değeri belirtmenin gerekli olmadığını unutmayın. Bunun nedeni, animasyonun orijinal değeri izleyebilmesidir.

<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 Taslaklarına genel bakış.

Aşağıdaki çizimde fare üçüncü öğeyi işaret ediyor.

Stil oluşturma örneği ekran görüntüsü

Çoklu Tetikleyiciler, Veri Tetikleyicileri ve Çoklu Veri Tetikleyicileri

Trigger ve 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. Koşulunuzun özelliği veriye bağlı olduğunda DataTrigger ve MultiDataTrigger kullanırsınız.

Görsel Durumlar

Denetimler her zaman belirli bir durumundadır. Örneğin, fare bir denetimin yüzeyinin üzerinde hareket ettiğinde, denetimin MouseOverortak bir durumda olduğu kabul edilir. Belirli bir durumu olmayan bir denetimin ortak Normal durumu içinde olduğu kabul edilir. Durumlar gruplara ayrılır ve daha önce bahsedilen durumlar CommonStatesdurum grubunun bir parçasıdır. Çoğu denetimin iki durum grubu vardır: CommonStates ve FocusStates. Denetime uygulanan her durum grubunda, denetim her zaman CommonStates.MouseOver ve FocusStates.Unfocusedgibi her grubun tek bir durumunda olur. Ancak, bir denetim CommonStates.Normal ve CommonStates.Disabledgibi 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 Kontrol tuşuna basılır.
Disabled CommonStates Denetim devre dışı bırakıldı.
Focused FocusStates Kontrol odaklanmış durumda.
Unfocused FocusStates Kontrolün odak noktası yok.

Denetim şablonunun kök öğesinde bir System.Windows.VisualStateManager tanımlayarak, bir denetim belirli bir duruma girdiğinde animasyonları tetikleyebilirsiniz. VisualStateManager, hangi VisualStateGroup ve VisualState bileşimlerinin izleyebileceğinizi bildirir. Denetim izlenen duruma girdiğinde, VisualStateManager tarafından tanımlanan animasyon başlatılır.

Örneğin, aşağıdaki XAML kodu CommonStates.MouseOveradlı öğenin dolgu rengine animasyon eklemek için backgroundElement durumunu izler. Denetim CommonStates.Normal durumuna döndüğünde, backgroundElement adlı öğ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, ResourceDictionary sınıfı olarak kapsüllenmiş bir kaynak sözlüğü kullanarak ui kaynaklarını tema olarak paketleme desteği 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.dlliçin, WPF denetimlerini içeren derlemedeki tema kaynakları, bir dizi yan yana duran derlemenin içinde 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 ResourceDictionary dosyasına başvuru içeren bir shared.xaml tanımlayabilirsiniz.

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

shared.xamlpaylaşımının kendisinin, stil ve fırça kaynakları kümesi içeren bir ResourceDictionary tanımlaması ve bu paylaşımın, bir uygulamadaki denetimlerin tutarlı bir görünüme sahip olmasını sağlamasıdır.

Daha fazla bilgi için bkz. Birleştirilmiş kaynak sözlükleri.

Özel denetiminiz için bir tema oluşturuyorsanız, Denetimi Yazmaya Genel Bakışbölümünün Tema Düzeyinde Kaynak Tanımlama kısmına bakın.

Ayrıca bakınız