Ресурсы и стили. Стили в WPF

Стили в WPF позволяют отделить визуальное оформление элемента управления от его основного кода и представляют собой набор свойств и их значений, которые могут применяться к элементам управления. Как и ресурсы, стили определяются в словаре ResourceDictionary, однако, в отличие от ресурсов для их определения используются специальные объекту Style. В этой части мы рассмотрим применение стилей в WPF.

Пример использования стилей в приложении WPF

Часто наши приложения содержат ряд однотипных элементов управления с одинаковым оформлением. Например, рассмотрим следующий XAML-код

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <StackPanel>
        <Button Background="LightBlue"
                Foreground="DarkBlue"
                FontSize="14"
                Content="Кнопка №1"
                Padding="5"
                Margin="5"/>
        <Button Background="LightBlue"                
                Foreground="DarkBlue"
                FontSize="14"
                Content="Кнопка №2"
                Padding="5"
                Margin="5"/>
    </StackPanel>
</Window>

Здесь две кнопки имеют абсолютно одинаковое оформление, различается только их текст.

Стили WPF

И таких кнопок может быть в приложении десятки. Вынесение оформления элемента управления в стиль позволяет сделать основной код более лаконичным и читаемым. Рассмотрим применение стилей WPF на следующем примере:

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <Style TargetType="Button" x:Key="button">
            <Setter Property="Background"
                    Value="LightBlue"/>
            <Setter Property="Foreground"
                    Value="DarkBlue"/>
            <Setter Property="FontSize"
                    Value="14"/>
            <Setter Property="Padding"
                    Value="5"/>
            <Setter Property="Margin"
                    Value="5"/>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <Button Style="{StaticResource button}" Content="Кнопка №1"/>
        <Button Style="{StaticResource button}" Content="Кнопка №2"/>
    </StackPanel>
</Window>

Здесь мы используем объект Style для определения стиля кнопки. Чтобы указать к какому элементу управления относится стиль, мы используем свойство TargetType:

<Style TargetType="Button" x:Key="button">

Далее, используя коллекцию Setters, мы добавляем в стиль элементы типа Setter, каждый из которых определяет свойство и его значение для объекта, указанного в TargetType. В нашем примере, мы опустили объявление свойства Setters и сразу перечислили необходимые элементы Setter. Полная запись стиля могла бы выглядеть так:

<Style TargetType="Button" x:Key="button">
    <Style.Setters>
        <Setter Property="Background"
Value="LightBlue"/>
        <Setter Property="Foreground"
Value="DarkBlue"/>
        <Setter Property="FontSize"
Value="14"/>
        <Setter Property="Padding"
Value="5"/>
        <Setter Property="Margin"
Value="5"/>
    </Style.Setters>
</Style>

Каждый объект Setter содержит два важных для нас свойства:

  • Property — имя свойства
  • Value — его значение

Определив стиль, мы можем его использовать в приложение также, как и ресурсы, то есть с использованием расширений XAML StaticResource или DynamicResource и применяется это расширение к свойству Style элемента управления. В нашем случае, мы использовали стиль как статический и применили его к обеим кнопкам:

<StackPanel>
    <Button Style="{StaticResource button}" Content="Кнопка №1"/>
    <Button Style="{StaticResource button}" Content="Кнопка №2"/>
</StackPanel>

Внешний вид приложения при этом не поменяется, однако его код становится более лаконичным. Более того, так как стиль — это, по сути, особый вид ресурсов, то мы могли бы вынести его в отдельный файл, сделав основной код окна ещё более коротким.

Общие (неявные) стили WPF

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

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <Style TargetType="Button">
            <Style.Setters>
                <Setter Property="Background"
        Value="LightBlue"/>
                <Setter Property="Foreground"
        Value="DarkBlue"/>
                <Setter Property="FontSize"
        Value="14"/>
                <Setter Property="Padding"
        Value="5"/>
                <Setter Property="Margin"
        Value="5"/>
            </Style.Setters>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <Button Content="Кнопка №1"/>
        <Button Content="Кнопка №2"/>
    </StackPanel>
</Window>

Так как наш стиль не имеет ключа x:Key, то он автоматически применяется ко всем кнопкам приложения.

Приоритет стилей

Стили элементов управления, как и ресурсы, могут определяться на разных уровнях иерархии: на уровне страницы, приложения и т.д. Более того, в приложении может быть определено несколько общих стилей для одного и того же типа элементов управления. Поэтому в WPF действует правило: стили, расположенные на более низком уровне иерархии имею более высокий приоритет. Например, изменим код нашего приложения следующим образом:

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <Style TargetType="Button">
            <Style.Setters>
                <Setter Property="Background"
        Value="LightBlue"/>
                <Setter Property="Foreground"
        Value="DarkBlue"/>
                <Setter Property="FontSize"
        Value="14"/>
                <Setter Property="Padding"
        Value="5"/>
                <Setter Property="Margin"
        Value="5"/>
            </Style.Setters>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <Button Content="Кнопка №1">
            <Button.Resources>
                <Style TargetType="Button">
                    <Style.Setters>
                        <Setter Property="Background" Value="Pink"/>
                        <Setter Property="Foreground" Value="DarkRed"/>
                        <Setter Property="FontSize" Value="16"/>
                        <Setter Property="Padding" Value="5"/>
                        <Setter Property="Margin" Value="5"/>
                    </Style.Setters>
                </Style>
            </Button.Resources>
        </Button>
        <Button Content="Кнопка №2"/>
    </StackPanel>
</Window>

Здесь определены два общих стиля на разных уровнях:

  1. Стиль на уровне окна
  2. Стиль на уровне элемента управления (у кнопки «Кнопка №1»)

Так как стиль определенный на уровне кнопки находится ниже в иерархии, то он будет иметь более высокий приоритет. Поэтому, если запустить приложение, то вы увидите следующий вид кнопок:

Такое же поведение характерно и в том случае, если вы решите изменить одно или несколько свойств объекта, которые перечислены в стиле. Например,
<StackPanel>
    <Button Content="Кнопка №1" Background="LightCoral"/>
    <Button Content="Кнопка №2"/>
</StackPanel>

Теперь первая кнопка изменит свой внешний вид:

Наследование стилей и классы стилей

Стили можно наследовать. Для этого используется свойство стиля BaseOn. Например,

<Window.Resources>
    <ResourceDictionary>
        <Style TargetType="Button" x:Key="BaseButtonStyle">
            <Style.Setters>
                <Setter Property="Background" Value="LightBlue"/>
                <Setter Property="Foreground" Value="DarkBlue"/>
                
            </Style.Setters>
        </Style>

        <Style TargetType="Button" x:Key="ButtonStyle" BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="FontSize" Value="14"/>
            <Setter Property="Padding" Value="5"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
    </ResourceDictionary>
    
</Window.Resources>

<StackPanel>
    <Button Style="{StaticResource ButtonStyle}" Content="Кнопка №1" Background="LightCoral"/>
    <Button Style="{StaticResource ButtonStyle}" Content="Кнопка №2"/>
</StackPanel>

Здесь мы определили в словаре ресурсов два стиля с именами BaseButtonStyle и ButtonStyle, причем второй стиль использует атрибут BasedOn, то есть наследуется от BaseButtonStyle . Теперь, в зависимости от ситуации, мы можем использовать для кнопок различные стили, например, так:

<StackPanel>
    <Button Style="{StaticResource BaseButtonStyle}" Content="Кнопка №1" Background="LightCoral"/>
    <Button Style="{StaticResource ButtonStyle}" Content="Кнопка №2"/>
</StackPanel>

Стили WPF

Итого

Стили в WPF позволяют вынести визуальное оформление элементов управления в ресурсы, изолировав их, тем самым, от основной части кода приложения. Стиль может применяться как ко всем элементам определенного типа, так и по отдельности. Также, стили могут наследоваться с использованием атрибута BasedOn.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии