Denetim için şablon oluşturma (WPF.NET)

Windows Presentation Foundation (WPF) ile mevcut bir denetimin görsel yapısını ve davranışını kendi yeniden kullanılabilir şablonunuzla özelleştirebilirsiniz. Şablonlar uygulamanıza, pencerelerinize ve sayfalarınıza genel olarak veya doğrudan denetimlere uygulanabilir. Yeni denetim oluşturmanızı gerektiren senaryoların çoğu, bunun yerine mevcut bir denetim için yeni bir şablon oluşturularak ele alınabilir.

Önemli

.NET 7 ve .NET 6 için Masaüstü Kılavuzu belgeleri yapım aşamasındadır.

Bu makalede, denetim için yeni ControlTemplate bir oluşturma işlemini Button keşfedeceksiniz.

ControlTemplate ne zaman oluşturulur?

Denetimlerin , Foregroundve FontFamilygibi Backgroundbirçok özelliği vardır. Bu özellikler denetimin görünümünün farklı yönlerini denetler, ancak bu özellikleri ayarlayarak yapabileceğiniz değişiklikler sınırlıdır. Örneğin, özelliğini bir üzerinde CheckBoxmavi ve FontStyle italik olarak ayarlayabilirsinizForeground. Denetimin görünümünü, denetimdeki diğer özellikleri ayarlamanın yapabileceklerinin ötesinde özelleştirmek istediğinizde, bir ControlTemplateoluşturursunuz.

Çoğu kullanıcı arabiriminde, bir düğme aynı genel görünüme sahiptir: metin içeren bir dikdörtgen. Yuvarlatılmış düğme oluşturmak istiyorsanız, düğmeden devralan veya düğmenin işlevselliğini yeniden oluşturan yeni bir denetim oluşturabilirsiniz. Buna ek olarak, yeni kullanıcı denetimi döngüsel görseli sağlar.

Mevcut bir denetimin görsel düzenini özelleştirerek yeni denetimler oluşturmaktan kaçınabilirsiniz. Yuvarlatılmış bir düğmeyle, istediğiniz görsel düzeni içeren bir ControlTemplate oluşturursunuz.

Öte yandan, yeni işlevlere, farklı özelliklere ve yeni ayarlara sahip bir denetime ihtiyacınız varsa, yeni UserControlbir oluşturursunuz.

Ön koşullar

Yeni bir WPF uygulaması oluşturun ve MainWindow.xaml dosyasında (veya seçtiğiniz başka bir pencerede) Window> öğesinde< aşağıdaki özellikleri ayarlayın:

Özellik Değer
Title Template Intro Sample
SizeToContent WidthAndHeight
MinWidth 250

Window> öğesinin <içeriğini aşağıdaki XAML olarak ayarlayın:

<StackPanel Margin="10">
    <Label>Unstyled Button</Label>
    <Button>Button 1</Button>
    <Label>Rounded Button</Label>
    <Button>Button 2</Button>
</StackPanel>

Sonunda MainWindow.xaml dosyası aşağıdakine benzer görünmelidir:

<Window x:Class="IntroToStylingAndTemplating.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IntroToStylingAndTemplating"
        mc:Ignorable="d"
        Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250">
    <StackPanel Margin="10">
        <Label>Unstyled Button</Label>
        <Button>Button 1</Button>
        <Label>Rounded Button</Label>
        <Button>Button 2</Button>
    </StackPanel>
</Window>

Uygulamayı çalıştırırsanız aşağıdaki gibi görünür:

WPF window with two unstyled buttons

ControlTemplate oluşturma

bildirmenin ControlTemplate en yaygın yolu, XAML dosyasının Resources bölümündeki bir kaynaktır. Şablonlar kaynak olduğundan, tüm kaynaklar için geçerli olan aynı kapsam kurallarına uyarlar. Basitçe söylemek gerekirse, bir şablonu bildirdiğiniz yer, şablonun uygulanabileceği yeri etkiler. Örneğin, şablonu uygulama tanımı XAML dosyanızın kök öğesinde bildirirseniz, şablon uygulamanızın herhangi bir yerinde kullanılabilir. Şablonu bir pencerede tanımlarsanız, şablonu yalnızca bu penceredeki denetimler kullanabilir.

Başlangıç olarak MainWindow.xaml dosyanıza bir Window.Resources öğe ekleyin:

<Window x:Class="IntroToStylingAndTemplating.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IntroToStylingAndTemplating"
        mc:Ignorable="d"
        Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250">
    <Window.Resources>
        
    </Window.Resources>
    <StackPanel Margin="10">
        <Label>Unstyled Button</Label>
        <Button>Button 1</Button>
        <Label>Rounded Button</Label>
        <Button>Button 2</Button>
    </StackPanel>
</Window>

Aşağıdaki özellikler kümesiyle yeni <bir ControlTemplate> oluşturun:

Özellik Değer
x:Key roundbutton
TargetType Button

Bu denetim şablonu basit olacaktır:

  • denetim için bir kök öğesi, bir Grid
  • düğmenin yuvarlatılmış görünümünü çizmek için bir Ellipse
  • kullanıcı tarafından belirtilen düğme içeriğini görüntülemek için a ContentPresenter
<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

Templatebinding

Yeni ControlTemplatebir oluşturduğunuzda, yine de denetimin görünümünü değiştirmek için genel özellikleri kullanmak isteyebilirsiniz. TemplateBinding işaretleme uzantısı, içindeki bir öğenin ControlTemplate özelliğini denetim tarafından tanımlanan bir ortak özelliğe bağlar. TemplateBinding kullandığınızda, şablona parametre işlevi görmesi için denetimdeki özellikleri etkinleştirirsiniz. Başka bir ifadeyle, bir denetimdeki bir özellik ayarlandığında, bu değer üzerinde TemplateBinding bulunan öğeye geçirilir.

Elips

Elips öğesinin Fill ve Stroke özelliklerinin <denetimin Foreground ve Background özelliklerine bağlı olduğuna dikkat edin.>

Contentpresenter

Şablona <bir ContentPresenter> öğesi de eklenir. Bu şablon bir düğme için tasarlandığından, düğmenin öğesinden ContentControldevralındığını dikkate alın. düğme, öğesinin içeriğini gösterir. Düğmenin içinde düz metin ve hatta başka bir denetim gibi her şeyi ayarlayabilirsiniz. Aşağıdakilerin her ikisi de geçerli düğmelerdir:

<Button>My Text</Button>

<!-- and -->

<Button>
    <CheckBox>Checkbox in a button</CheckBox>
</Button>

Önceki örneklerin her ikisinde de metin ve onay kutusu Button.Content özelliği olarak ayarlanmıştır. İçerik olarak ayarlanan içerik contentPresenter ><aracılığıyla sunulabilir. Bu, şablonun yaptığı işlemdir.

ControlTemplate gibi bir ContentControl türe Buttonuygulanırsa, ContentPresenter öğe ağacında için aranılır. ContentPresenter bulunursa, şablon denetimin Content özelliğini ContentPresenteröğesine otomatik olarak bağlar.

Şablonu kullanma

Bu makalenin başında bildirilen düğmeleri bulun.

<StackPanel Margin="10">
    <Label>Unstyled Button</Label>
    <Button>Button 1</Button>
    <Label>Rounded Button</Label>
    <Button>Button 2</Button>
</StackPanel>

İkinci düğmenin Template özelliğini roundbutton kaynağa ayarlayın:

<StackPanel Margin="10">
    <Label>Unstyled Button</Label>
    <Button>Button 1</Button>
    <Label>Rounded Button</Label>
    <Button Template="{StaticResource roundbutton}">Button 2</Button>
</StackPanel>

Projeyi çalıştırır ve sonucuna bakarsanız düğmenin yuvarlatılmış bir arka planı olduğunu görürsünüz.

WPF window with one template oval button

Düğmenin daire olmadığını ancak çarpık olduğunu fark etmiş olabilirsiniz. Elips> öğesinin <çalışma şekli nedeniyle, her zaman kullanılabilir alanı dolduracak şekilde genişler. Düğme widthheight ve özelliklerini aynı değerle değiştirerek daireyi tekdüzen hale getirin:

<StackPanel Margin="10">
    <Label>Unstyled Button</Label>
    <Button>Button 1</Button>
    <Label>Rounded Button</Label>
    <Button Template="{StaticResource roundbutton}" Width="65" Height="65">Button 2</Button>
</StackPanel>

WPF window with one template circular button

Tetikleyici Ekleme

Şablon uygulanmış bir düğme farklı görünse de, diğer tüm düğmelerle aynı şekilde davranır. Düğmeye basarsanız olay Click tetikler. Ancak farenizi düğmenin üzerine taşıdığınızda düğmenin görsellerinin değişmediğini fark etmiş olabilirsiniz. Bu görsel etkileşimlerin tümü şablon tarafından tanımlanır.

WPF'nin sağladığı dinamik olay ve özellik sistemleriyle, bir değer için belirli bir özelliği izleyebilir ve uygun olduğunda şablonu restyle yapabilirsiniz. Bu örnekte düğmenin IsMouseOver özelliğini izleyeceksiniz. Fare denetimin üzerindeyken, Elips'e ><yeni bir renk verin. Bu tetikleyici türü PropertyTrigger olarak bilinir.

Bunun işe yarayabilmesi için Başvurabileceğiniz Elips'e ><bir ad eklemeniz gerekir. Ona backgroundElement adını verin.

<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />

Ardından, ControlTemplate.Triggers koleksiyonuna yeni Trigger bir ekleyin. Tetikleyici değeri trueiçin olayını izlerIsMouseOver.

<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="true">

        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Ardından, Tetikleyiciye><Elips'in> Fill özelliğini< yeni bir renkle değiştiren bir Ayarlayıcı> ekleyin.<

<Trigger Property="IsMouseOver" Value="true">
    <Setter Property="Fill" TargetName="backgroundElement" Value="AliceBlue"/>
</Trigger>

Projeyi çalıştırma. Fareyi düğmenin üzerinde hareket ettirdiğinizde, Elips> renginin değiştiğine <dikkat edin.

mouse moves over WPF button to change the fill color

VisualState kullanma

Görsel durumlar bir denetim tarafından tanımlanır ve tetiklenir. Örneğin, fare denetimin üzerine taşındığında durum CommonStates.MouseOver tetiklenmiş olur. Denetimin geçerli durumuna göre özellik değişikliklerine animasyon ekleyebilirsiniz. Önceki bölümde, özelliğin olduğu düğmenin arka planını olarak değiştirmek için bir <PropertyTrigger> kullanılmıştırtrue.AliceBlueIsMouseOver Bunun yerine, bu rengin değişikliğine animasyon uygulayan ve sorunsuz bir geçiş sağlayan bir görsel durum oluşturun. VisualStates hakkında daha fazla bilgi için bkz. WPF'de Stiller ve şablonlar.

PropertyTrigger'ı animasyonlu görsel durumuna dönüştürmek için öncelikle ControlTemplate.Triggers> öğesini şablonunuzdan kaldırın<.<>

<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

Ardından, denetim şablonunun <Kılavuz> kökünde, için CommonStatesbir< VisualStateGroup> ile VisualStateManager.VisualStateGroups> öğesini ekleyin.< ve iki durum NormalMouseOvertanımlayın.

<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                </VisualState>
                <VisualState Name="MouseOver">
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

Bir VisualState'te ><tanımlanan tüm animasyonlar, bu durum tetiklendiğinde uygulanır. Her durum için animasyonlar oluşturun. Animasyonlar görsel <taslak> öğesinin içine konur. Görsel taslaklar hakkında daha fazla bilgi için bkz . Görsel Taslaklara Genel Bakış.

  • Normal

    Bu durum, elips dolgusunun animasyonunu oluşturur ve denetimin Background rengine geri yükler.

    <Storyboard>
        <ColorAnimation Storyboard.TargetName="backgroundElement" 
            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
            To="{TemplateBinding Background}"
            Duration="0:0:0.3"/>
    </Storyboard>
    
  • Mouseover

    Bu durum, üç nokta Background rengine yeni bir renge animasyon ekler: Yellow.

    <Storyboard>
        <ColorAnimation Storyboard.TargetName="backgroundElement" 
            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" 
            To="Yellow" 
            Duration="0:0:0.3"/>
    </Storyboard>
    

<ControlTemplate> artık aşağıdaki gibi görünmelidir.

<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="backgroundElement" 
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
                            To="{TemplateBinding Background}"
                            Duration="0:0:0.3"/>
                    </Storyboard>
                </VisualState>
                <VisualState Name="MouseOver">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetName="backgroundElement" 
                            Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" 
                            To="Yellow" 
                            Duration="0:0:0.3"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Ellipse Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

Projeyi çalıştırma. Fareyi düğmenin üzerinde hareket ettirdiğinizde, Üç Nokta> animasyonunun rengine <dikkat edin.

mouse moves over WPF button to change the fill color with a visual state

Sonraki adımlar