Стили применяются для создания единообразного отображения элементов, также они упрощают подключения группы ресурсов к отдельным элементам. Стили позволяют определить набор некоторых свойств и их значений, которые потом могут применяться к элементам в xaml. Стили хранятся в ресурсах и отделяют значения свойств элементов от пользовательского интерфейса. Аналогом стилей могут служить каскадные таблицы стилей (CSS), которые применяются в коде html на веб-страницах.
Допустим, у нас есть следующий код xaml:
<StackPanel x:Name="buttonsStack"> <Button x:Name="button1" Content="Кнопка 1" Margin="10" FontFamily="Verdana" Foreground="#ecf0f1" Background="#34495e" /> <Button x:Name="button2" Content="Кнопка 2" Margin="10" FontFamily="Verdana" Foreground="#ecf0f1" Background="#34495e"/> </StackPanel>
Обе кнопки применяют ряд свойств с одними и теми же значениями. Фактически они используют один и тот же стиль. Поэтому чтобы избежать ненужного дублирования гораздо проще создать стиль как отдельный объект и затем подключать его к кнопкам:
<Page x:Class="BindingApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BindingApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Style x:Key="ButtonStyle" TargetType="Button" > <Setter Property="Control.FontFamily" Value="Verdana" /> <Setter Property="Control.Background" Value="#34495e" /> <Setter Property="Control.Foreground" Value="#ecf0f1" /> <Setter Property="Control.Margin" Value="10" /> </Style> </Page.Resources> <StackPanel x:Name="buttonsStack" > <Button x:Name="button1" Content="Кнопка 1" Style="{StaticResource ButtonStyle}" /> <Button x:Name="button2" Content="Кнопка 2" Style="{StaticResource ButtonStyle}"/> </StackPanel> </Page>
Результат будет тот же, однако теперь мы избегаем не нужного повторения. Более того теперь мы можем управлять всеми нужными нам свойствами как единым целым - одним стилем.
Стиль создается как ресурс с помощью объекта Style, который представляет класс Windows.UI.Xaml.Style. Как у всякого ресурса,
у стиля устанавливается ключ с помощью атрибута x:Key
, а также свойство TargetType - оно указывает на тип элементов,
к которым применяется стиль.
Внутри стиля в коллекции Setters создаются объекты Setter. Они определяют свойства стилизации и их значения с помощью следующих атрибутов:
Property: указывает на свойство, к которому будет применяться данный сеттер. Имеет следующий синтаксис:
Property="Тип_элемента.Свойство_элемента"
Выше в качестве типа элемента использовался Control, как общий для всех элементов. Поэтому данный стиль мы могли бы применить и к Button, и к другим элементам, который унаследованы от типа Control. Однако мы можем и конкретизировать элемент, например, Button:
<Setter Property="Button.FontFamily" Value="Arial" />
Value: устанавливает значение для свойства из Property
Если значение свойства представляет сложный объект, то мы можем его вынести в отдельный элемент:
<Style x:Key="ButtonStyle" TargetType="Button"> <Setter Property="Control.Background"> <Setter.Value> <LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1"> <LinearGradientBrush.GradientStops> <GradientStop Color="White" Offset="0" /> <GradientStop Color="Black" Offset="1" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="Control.FontFamily" Value="Verdana" /> <Setter Property="Control.Foreground" Value="White" /> <Setter Property="Control.Margin" Value="10" /> </Style>
Hам необязательно прописывать для всех кнопок стиль. Достаточно с помощью свойства TargetType задать тип элементов. В этом случае ключ ресурса в стиле не указывается, а сам стиль будет автоматически применяться ко всем кнопкам в окне:
<Page x:Class="BindingApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BindingApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Style TargetType="Button" > <Setter Property="Control.FontFamily" Value="Verdana" /> <Setter Property="Control.Background" Value="#34495e" /> <Setter Property="Control.Foreground" Value="#ecf0f1" /> <Setter Property="Control.Margin" Value="10" /> </Style> </Page.Resources> <StackPanel x:Name="buttonsStack" > <Button x:Name="button1" Content="Кнопка 1" /> <Button x:Name="button2" Content="Кнопка 2" /> </StackPanel> </Page>
Также если используем свойство TargetType без ключа ресурса, то у атрибута Property уже необязательно указывать тип, то есть
Property="Control.FontFamily"
. И в данном случае тип можно просто опустить: Property="FontFamily"
Если же необходимо, чтобы к какой-то кнопке не применялся автоматический стиль, то ее стилю присваивают значение null
:
<Button x:Name="button2" Content="Кнопка 2" Style="{x:Null}" />
С помощью свойства BasedOn мы можем наследовать стили:
<Page.Resources> <Style x:Key="ButtonParentStyle" TargetType="Button"> <Setter Property="Button.Background" Value="Black" /> <Setter Property="Button.Foreground" Value="White" /> <Setter Property="Button.FontFamily" Value="Arial" /> </Style> <Style x:Key="ButtonChildStyle" TargetType="Button" BasedOn="{StaticResource ButtonParentStyle}"> <Setter Property="Button.BorderBrush" Value="Red" /> <Setter Property="Button.FontFamily" Value="Verdana" /> </Style> </Page.Resources>
Cвойство BasedOn в качестве значения принимает ссылку на уже существующий стиль и объединяет его функционал со своим собственным.
Если в дочернем стиле есть сеттеры для свойств, которые также используются в родительском стиле, как в данном случае сеттер для свойства Button.FontFamily, то дочерний стиль переопределяет родительский стиль.
В C# стили представляют объект Windows.UI.Xaml.Style. Используя его, мы можем добавлять сеттеры и устанавливать стиль для нужных элементов:
using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; using Windows.UI; namespace BindingApp { public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); Style buttonStyle = new Style(); buttonStyle.Setters.Add(new Setter { Property = Control.FontFamilyProperty, Value = new FontFamily("Verdana") }); buttonStyle.Setters.Add(new Setter { Property = Control.MarginProperty, Value = new Thickness(10) }); buttonStyle.Setters.Add(new Setter { Property = Control.BorderBrushProperty, Value = new SolidColorBrush(Colors.Gray) }); buttonStyle.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = new SolidColorBrush(Colors.Black) }); buttonStyle.Setters.Add(new Setter { Property = Control.ForegroundProperty, Value = new SolidColorBrush(Colors.White) }); buttonStyle.TargetType = typeof(Button); button1.Style = buttonStyle; button2.Style = buttonStyle; } } }
Чтобы создать сеттер, нужно использовать свойство зависимостей, например, Property = Control.FontFamilyProperty
.
Причем для свойства Value у сеттера должен быть установлен объект именно того типа, которое хранится в этом свойстве зависимости.
Так, свойство зависимости MarginProperty
представляет объект Thickness
, поэтому определение сеттера выглядит следующим образом:
new Setter { Property = Control.MarginProperty, Value = new Thickness(10) }