Создание стиля элемента управления

С помощью Windows Presentation Foundation (WPF) можно настроить внешний вид существующего элемента управления, создав собственный стиль повторного использования. Стили можно применять глобально к приложению, окнам и страницам или напрямую к элементам управления.

Создание стиля

Думайте о Style удобном способе применения набора значений свойств к одному или нескольким элементам. Стиль можно использовать для любого элемента, происходящего от FrameworkElement или FrameworkContentElement, например для Window или Button.

Наиболее распространенный способ задать стиль — это использование ресурса в разделе Resources XAML-файла. Поскольку стили являются ресурсами, они следуют тем же правилам области, что и все ресурсы. Где вы объявляете стиль, влияет на то, где его можно применить. Например, если вы объявляете стиль в корневом элементе XAML-файла определения приложения, вы можете использовать стиль в любом месте приложения.

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

Если вы объявляете стиль в одном из XAML-файлов приложения, вы можете использовать стиль только в этом XAML-файле. Дополнительные сведения о правилах определения области для ресурсов см. в статье Общие сведения о ресурсах 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>

Стиль состоит из дочерних <Setter> элементов, которые задают свойства элементов, к которым применяется стиль. В предыдущем примере стиль через атрибут TargetType применяется к типам TextBlock. Стиль устанавливает FontSize как 15, а FontWeight как ExtraBold. Добавьте <Setter> для каждого свойства, которое изменяет стиль.

Неявное применение стиля

Style обеспечивает удобный способ применения набора значений свойств к нескольким элементам. Рассмотрим, к примеру, следующие элементы TextBlock и их внешний вид по умолчанию в окне.

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

Снимок экрана: пример стилизации до

Внешний вид по умолчанию можно изменить, задав такие свойства, как FontSize и FontFamily, непосредственно в каждом элементе TextBlock. Но если вы хотите, чтобы элементы TextBlock могли совместно использовать некоторые свойства, можно создать Style в разделе Resources файла XAML, как показано ниже.

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

Когда вы устанавливаете TargetType вашего стиля на тип TextBlock и опускаете атрибут x:Key, стиль применяется ко всем TextBlock элементам, предназначенным для данного стиля, который обычно является самим файлом XAML.

Теперь элементы TextBlock выглядят следующим образом.

Снимок экрана примера базового стиля оформления

Примените стиль явно

Если вы добавляете атрибут x:Key со значением в стиль, стиль больше не применяется неявно ко всем элементам TargetType. Только элементы, которые явно ссылаются на стиль, получают его.

Ниже приведен стиль из предыдущего раздела, но объявленный атрибутом 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>

Чтобы применить стиль, задайте свойство Style элемента на значение x:Key с помощью расширения разметки StaticResource, как показано ниже.

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

Обратите внимание, что стиль применен к первому элементу TextBlock, а второй элемент TextBlock остается неизменным. Неявный стиль из предыдущего раздела изменился на стиль, объявленный атрибутом x:Key . Стиль влияет только на элементы, ссылающиеся на него напрямую.

Снимок экрана: пример стилизации текстового блока

После явного или неявного применения стиля он становится запечатанным и не может быть изменен. Если вы хотите изменить стиль, создайте новый стиль для замены существующего. Дополнительные сведения см. в свойстве IsSealed.

Можно создать объект, который выбирает стиль, который нужно применить, основываясь на собственной логике. Ознакомьтесь с примером для класса StyleSelector.

Применение стиля программным способом

Чтобы назначить именованный стиль элементу программным способом, возьмите стиль из коллекции ресурсов и присвойте его свойству Style этого элемента. Обратите внимание, что элементы в коллекции ресурсов имеют тип Object. Поэтому полученный стиль необходимо привести к System.Windows.Style, прежде чем назначать его свойству Style. Например, следующий код задает стиль TextBlock с именем textblock1 определенному стилю TitleText.

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

Расширение стиля

Возможно, вы захотите, чтобы два TextBlock элемента имели общие значения свойств, такие как FontFamily и центрированные HorizontalAlignment. При этом текст Мои рисунки должен иметь некоторые дополнительные свойства. Это можно сделать, создав новый стиль, основанный на первом стиле, как показано в следующем примере.

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

Затем примените стиль к TextBlock.

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

Этот TextBlock стиль теперь центрирован, использует Comic Sans MS шрифт с размером 26и задает цвет LinearGradientBrush переднего плана показанным в примере. Он переопределяет FontSize значение базового стиля. Если несколько Setter указывают на одно и то же свойство в Style, приоритет имеет свойство Setter, объявленное последним.

На следующем рисунке показано, как выглядят элементы TextBlock сейчас:

Стилизованные TextBlock'и

Этот TitleText стиль расширяет стиль, который вы создали для TextBlock типа, на который ссылаются с помощью BasedOn="{StaticResource {x:Type TextBlock}}". Вы также можете расширить стиль с x:Key, воспользовавшись x:Key этого стиля. Например, если существовал стиль с именем Header1, который вы хотите расширить, используйте BasedOn="{StaticResource Header1}".

Связь между свойством TargetType и атрибутом x:Key

Как показано ранее, установка свойства TargetType на TextBlock без назначения стиля x:Key приводит к применению стиля ко всем TextBlock элементам. В этом случае для x:Key неявно устанавливается значение {x:Type TextBlock}. Это поведение означает, что если вы явно задаете значение x:Key, отличное от {x:Type TextBlock}, оно автоматически не применяется ко всем элементам StyleTextBlock. Вместо этого необходимо явным образом применить стиль (используя значение x:Key) ко всем элементам TextBlock. Если стиль находится в разделе ресурсов и вы не задаете для стиля свойство TargetType, задайте атрибут x:Key.

Свойство x:Key не только предоставляет значение по умолчанию для TargetType, но и указывает тип, к которому применяются свойства метода задания. Если вы не указываете TargetType, вы должны указать свойства в объектах Setter с помощью имени класса с синтаксисом Property="ClassName.Property". Например, вместо установки Property="FontSize" необходимо задать для Property значение "TextBlock.FontSize" или "Control.FontSize".

Также обратите внимание, что многие элементы управления WPF представляют собой комбинацию других элементов управления WPF. Если создать стиль, который применяется ко всем элементам управления типа, можно получить непредвиденные результаты. Например, если вы создаете стиль, который нацелен на тип TextBlock в Window, этот стиль применяется ко всем элементам управления TextBlock в окне, даже если он является частью другого элемента управления, например ListBox.

См. также