Jak utworzyć styl kontrolki (WPF .NET)

Za pomocą programu Windows Presentation Foundation (WPF) możesz dostosować wygląd istniejącej kontrolki przy użyciu własnego stylu wielokrotnego użytku. Style można stosować globalnie do aplikacji, okien i stron lub bezpośrednio do kontrolek.

Ważne

Dokumentacja przewodnika dla komputerów dla platform .NET 7 i .NET 6 jest w budowie.

Tworzenie stylu

Można traktować Style jako wygodny sposób stosowania zestawu wartości właściwości do co najmniej jednego elementu. Możesz użyć stylu dla dowolnego elementu, który pochodzi z FrameworkElement lub FrameworkContentElement , na przykład Window lub Button.

Najbardziej typowym sposobem deklarowania stylu jest jako zasób w Resources sekcji w pliku XAML. Ponieważ style są zasobami, przestrzegają tych samych reguł określania zakresu, które mają zastosowanie do wszystkich zasobów. Mówiąc po prostu, gdzie deklarujesz styl, wpływa na to, gdzie można zastosować styl. Jeśli na przykład zadeklarujesz styl w elemecie głównym pliku XAML definicji aplikacji, styl może być używany w dowolnym miejscu w aplikacji.

<Application x:Class="IntroToStylingAndTemplating.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:IntroToStylingAndTemplating"
             StartupUri="WindowExplicitStyle.xaml">
    <Application.Resources>
        <ResourceDictionary>
            
            <Style x:Key="Header1" TargetType="TextBlock">
                <Setter Property="FontSize" Value="15" />
                <Setter Property="FontWeight" Value="ExtraBold" />
            </Style>
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

Jeśli zadeklarujesz styl w jednym z plików XAML aplikacji, styl może być używany tylko w tym pliku XAML. Aby uzyskać więcej informacji na temat reguł określania zakresu dla zasobów, zobacz Omówienie zasobów XAML.

<Window x:Class="IntroToStylingAndTemplating.WindowSingleResource"
        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="WindowSingleResource" Height="450" Width="800">
    <Window.Resources>
        
        <Style x:Key="Header1" TargetType="TextBlock">
            <Setter Property="FontSize" Value="15" />
            <Setter Property="FontWeight" Value="ExtraBold" />
        </Style>
        
    </Window.Resources>
    <Grid />
</Window>

Styl składa się z elementów podrzędnych <Setter> , które ustawiają właściwości elementów, do których jest stosowany styl. W powyższym przykładzie zwróć uwagę, że styl ma być stosowany do TextBlock typów za pomocą atrybutu TargetType . Styl zostanie ustawiony na FontSize15 wartość i na FontWeightExtraBoldwartość . Dodaj dla <Setter> każdej właściwości zmiany stylu.

Stosowanie stylu niejawnie

Jest Style to wygodny sposób stosowania zestawu wartości właściwości do więcej niż jednego elementu. Rozważmy na przykład następujące TextBlock elementy i ich domyślny wygląd w oknie.

<StackPanel>
    <TextBlock>My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Styling sample screenshot before

Wygląd domyślny można zmienić, ustawiając właściwości, takie jak FontSize i FontFamily, bezpośrednio dla każdego TextBlock elementu. Jeśli jednak chcesz TextBlock , aby elementy współużytkować niektóre właściwości, możesz utworzyć element Style w Resources sekcji pliku XAML, jak pokazano tutaj.

<Window.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>
</Window.Resources>

Po ustawieniu TargetType stylu TextBlock na typ i pominięcia atrybutu x:Key styl jest stosowany do wszystkich TextBlock elementów w zakresie stylu, który jest zazwyczaj plikiem XAML.

TextBlock Teraz elementy są wyświetlane w następujący sposób.

Styling sample screenshot base style

Jawne stosowanie stylu

Jeśli dodasz x:Key atrybut z wartością do stylu, styl nie będzie już niejawnie stosowany do wszystkich elementów elementu TargetType. Do nich zastosowano tylko elementy, które jawnie odwołują się do stylu.

Oto styl z poprzedniej sekcji, ale zadeklarowany za pomocą atrybutu x:Key .

<Window.Resources>
    <Style x:Key="TitleText" TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

Aby zastosować styl, ustaw Style właściwość elementu na x:Key wartość przy użyciu rozszerzenia znaczników StaticResource, jak pokazano tutaj.

<StackPanel>
    <TextBlock Style="{StaticResource TitleText}">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Zwróć uwagę, że pierwszy TextBlock element ma zastosowany styl, podczas gdy drugi element TextBlock pozostaje niezmieniony. Niejawny styl z poprzedniej sekcji został zmieniony na styl, który zadeklarował x:Key atrybut, co oznacza, że jedynym elementem, na który ma wpływ styl, jest ten, który odwoływał się bezpośrednio do stylu.

Styling sample screenshot textblock

Po zastosowaniu stylu jawnie lub niejawnie staje się zapieczętowany i nie można go zmienić. Jeśli chcesz zmienić zastosowany styl, utwórz nowy styl, aby zastąpić istniejący. Aby uzyskać więcej informacji, zobacz IsSealed właściwość .

Możesz utworzyć obiekt, który wybiera styl do zastosowania w oparciu o logikę niestandardową. Przykład można znaleźć w przykładzie podanym StyleSelector dla klasy .

Programowe stosowanie stylu

Aby programowo przypisać nazwany styl do elementu, pobierz styl z kolekcji zasobów i przypisz go do właściwości elementu Style . Elementy w kolekcji zasobów mają typ Object. W związku z tym należy rzutować pobrany styl na obiekt System.Windows.Style przed przypisaniem go do Style właściwości . Na przykład poniższy kod ustawia styl TextBlock nazwy na textblock1 zdefiniowany styl TitleText.

textblock1.Style = (Style)Resources["TitleText"];
textblock1.Style = CType(Resources("TitleText"), Windows.Style)

Rozszerzanie stylu

Być może chcesz, aby dwa TextBlock elementy współdzieliły niektóre wartości właściwości, takie jak FontFamily i wyśrodkowane HorizontalAlignment. Jednak chcesz również, aby tekst Moje obrazy miał pewne dodatkowe właściwości. Możesz to zrobić, tworząc nowy styl oparty na pierwszym stylu, jak pokazano tutaj.

<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>
<StackPanel>
    <TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Ten TextBlock styl jest teraz wyśrodkowany, używa Comic Sans MS czcionki o rozmiarze 26, a kolor pierwszego planu ustawiony na LinearGradientBrush pokazany w przykładzie. Zwróć uwagę, że zastępuje FontSize wartość stylu podstawowego. Jeśli istnieje więcej niż jedna Setter właściwość wskazująca tę samą właściwość w elemencie Style, Setter zadeklarowany ostatnio ma pierwszeństwo.

Poniżej przedstawiono, TextBlock jak wyglądają teraz elementy:

Styled TextBlocks

Ten TitleText styl rozszerza styl utworzony dla TextBlock typu, do którego odwołuje się BasedOn="{StaticResource {x:Type TextBlock}}"element . Można również rozszerzyć styl, który ma element x:Key przy użyciu x:Key stylu. Jeśli na przykład istnieje styl o nazwie Header1 i chcesz rozszerzyć ten styl, użyj polecenia BasedOn="{StaticResource Header1}".

Relacja właściwości TargetType i atrybutu x:Key

Jak pokazano wcześniej, ustawienie TargetType właściwości na TextBlock bez przypisywania stylu powoduje x:Key zastosowanie stylu do wszystkich TextBlock elementów. W tym przypadku parametr x:Key jest niejawnie ustawiony na {x:Type TextBlock}wartość . Oznacza to, że jeśli jawnie ustawisz x:Key wartość na wartość inną niż {x:Type TextBlock}, Style wartość nie zostanie automatycznie zastosowana do wszystkich TextBlock elementów. Zamiast tego należy zastosować styl (przy użyciu x:Key wartości) do TextBlock elementów jawnie. Jeśli styl znajduje się w sekcji zasobów i nie ustawisz TargetType właściwości w swoim stylu, musisz ustawić x:Key atrybut.

Oprócz podania wartości domyślnej x:Keydla właściwości właściwość TargetType określa typ, do którego mają zastosowanie właściwości setter. Jeśli nie określisz TargetTypeelementu , musisz zakwalifikować właściwości w Setter obiektach przy użyciu nazwy klasy przy użyciu składni Property="ClassName.Property". Na przykład zamiast ustawiać Property="FontSize"wartość , musisz ustawić "TextBlock.FontSize" wartość Property lub "Control.FontSize".

Należy również zauważyć, że wiele kontrolek WPF składa się z kombinacji innych kontrolek WPF. Jeśli utworzysz styl, który ma zastosowanie do wszystkich kontrolek typu, mogą zostać wyświetlone nieoczekiwane wyniki. Jeśli na przykład utworzysz styl docelowy TextBlock typu w Windowobiekcie , styl zostanie zastosowany do wszystkich TextBlock kontrolek w oknie, nawet jeśli TextBlock element jest częścią innej kontrolki, takiej jak ListBox.

Zobacz też