Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
Давайте построим стиль, который фиксирует базовые характеристики шрифта элемента управления в нашем приложении. Начните с создания в Visual Studio нового проекта приложения WPF по имени WpfStyles. Откройте файл App.xaml и определите в нем следующий именованный стиль:
<Application.Resources>
<Style x:Key="BasicControlStyle">
<Setter Property="Control.FontSize" Value="14"/>
<Setter Property="Control.Height" Value="40"/>
<Setter Property="Control.Cursor" Value="Hand"/>
</Style>
</Application.Resources>
Обратите внимание, что объект BasicControlStyle добавляет во внутреннюю коллекцию три объекта Setter. Теперь примените получившийся стиль к нескольким элементам управления в главном окне. Из-за того, что стиль является объектным ресурсом, элементы управления, которым он необходим, по-прежнему должны использовать расширение разметки {StackResource} или {DynamicResource} для нахождения стиля. Когда они находят стиль, то устанавливают элемент ресурса в идентично именованное свойство Style. Замените стандартный элемент управления Grid следующей разметкой:
<StackPanel>
<Label x:Name="lblInfo" Content="This style is boring..."
Style="{StaticResource BasicControlStyle}" Width="150"/>
<Button x:Name="btnTestButton" Content="Yes, but we are reusing settings!"
Style="{StaticResource BasicControlStyle}" Width="250"/>
</StackPanel>
Если вы просмотрите элемент Window в визуальном конструкторе Visual Studio (или запустите приложение), то обнаружите, что оба элемента управления поддерживают те же самые курсор, высоту и размер шрифта.
Переопределение настроек стиля
В то время как оба элемента управления подчиняются стилю, после применения стиля к элементу управления вполне допустимо изменять некоторые из определенных настроек. Например, элемент Button теперь использует курсор Help (вместо курсора Hand, определенного в стиле):
<Button x:Name="btnTestButton" Content="Yes, but we are reusing settings!"
Cursor="Help" Style="{StaticResource BasicControlStyle}" Width="250" />
Стили обрабатываются перед настройками индивидуальных свойств элемента управления, к которому применен стиль; следовательно, элементы управления могут "переопределять" настройки от случая к случаю.
Влияние атрибута TargetType на стили
В настоящий момент наш стиль определен так, что его может задействовать любой элемент управления (и он должен делать это явно, устанавливая свое свойство Style), поскольку каждое свойство уточнено посредством класса Control. Для программы, определяющей десятки настроек, в результате получился бы значительный объем повторяющегося кода. Один из способов несколько улучшить ситуацию предусматривает использование атрибута TargetType. Добавление атрибута TargetType к открывающему дескриптору Style позволяет точно указать, где стиль может быть применен (в данном примере внутри файла Арр.xaml):
<Style x:Key="BasicControlStyle" TargetType="Control">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Cursor" Value="Hand"/>
</Style>
На заметку! При построении стиля, использующего базовый класс, нет нужды беспокоиться о том, что значение присваивается свойству зависимости, которое не поддерживается производными типами. Если производный тип не поддерживает заданное свойство зависимости, то оно игнорируется.
Кое в чем прием помог, но все равно вы имеете стиль, который может применяться к любому элементу управления. Атрибут TargetType более удобен, когда необходимо определить стиль, который может быть применен только к отдельному типу элементов управления. Добавьте в словарь ресурсов приложения следующий стиль:
<Style x:Key="BigGreenButton" TargetType="Button">
<Setter Property="FontSize" Value="20"/>
<Setter Property="Height" Value="100"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Background" Value="DarkGreen"/>
<Setter Property="Foreground" Value="Yellow"/>
</Style>
Такой стиль будет работать только с элементами управления Button (или подклассами Button). Если применить его к несовместимому элементу, тогда возникнут ошибки разметки и компиляции. Добавьте элемент управления Button, который использует новый стиль:
<Button x:Name="btnAnotherButton" Content="OK!" Margin="0,10,0,0"
Style="{StaticResource BigGreenButton}" Width="250" Cursor="Help"/>
Результирующий вывод представлен на рис. 27.7.
Еще один эффект от атрибута TargetType заключается в том, что стиль будет применен ко всем элементам данного типа внутри области определения стиля при условии, что свойство х:Key отсутствует.
Вот еще один стиль уровня приложения, который будет автоматически применяться ко всем элементам управления TextBox в текущем приложении:
<!-- Стандартный стиль для всех текстовых полей -->
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="FontStyle" Value="Italic"/>
</Style>
Теперь можно определять любое количество элементов управления TextBox, и все они автоматически получат установленный внешний вид. Если какому-то элементу управления TextBox не нужен такой стандартный внешний вид, тогда он может отказаться от него, установив свойство StyleB {x:Null}. Например, элемент txtTest будет иметь неименованный стандартный стиль, а элемент txtTest2 сделает все самостоятельно:
<TextBox x:Name="txtTest"/>
<TextBox x:Name="txtTest2" Style="{x:Null}" BorderBrush="Black"
BorderThickness="5" Height="60" Width="100" Text="Ha!"/>
Создание подклассов существующих стилей
Новые стили можно также строить на основе существующего стиля посредством свойства BasedOn. Расширяемый стиль должен иметь подходящий атрибут х:Кеу в словаре, т.к. производный стиль будет ссылаться на него по имени, используя расширение разметки {StaticResource} или {DynamicResource}. Ниже представлен новый стиль, основанный на стиле BigGreenButton, который поворачивает элемент управления Button на 20 градусов:
<!-- Этот стиль основан на BigGreenButton -->
<Style x:Key="TiltButton" TargetType="Button"
BasedOn="{StaticResource BigGreenButton}">
<Setter Property="Foreground" Value="White"/>
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="20"/>
</Setter.Value>
</Setter>
</Style>
Чтобы применить новый стиль, модифицируйте разметку для кнопки следующим образом:
<Button x:Name="btnAnotherButton" Content="OK!" Margin="0,10,0,0"
Style="{StaticResource TiltButton}" Width="250" Cursor="Help"/>
Такое действие изменяет внешний вид изображения, как показано на рис. 27.8.
Определение стилей с триггерами
Стили WPF могут также содержать триггеры за счет упаковки объектов Trigger в коллекцию Triggers объекта Style. Использование триггеров в стиле позволяет определять некоторые элементы Setter таким образом, что они будут применяться только в случае истинности заданного условия триггера. Например, возможно требуется увеличивать размер шрифта, когда курсор мыши находится над кнопкой. Или, скажем, нужно подсветить текстовое поле, имеющее фокус, с использованием фона указанного цвета. Триггеры полезны в ситуациях подобного рода, потому что они позволяют предпринимать специфические действия при изменении свойства, не требуя написания явной логики С# в файле отделенного