rubezh-TWnlenfritplesuk

Стилизация TextBox в приложениях на WPF

Сегодня мы поговорим о том, как из стандартного серого и унылого WPF UI сделать красивый, приятный глазу юзерфрендли интерфейс.

Думаю я не отрою Америку, если скажу, что приложения на WPF достаточно просто видоизменить с помощью стилей.

Вот недавно занимался созданием стилей для одного из проектов на WPF - хотелось чтоб программа смотрелась немного современней, красочней, а не как бело-серое унылое чудо, как обычно получается при использовании стандартных стилей. Достаточно взглянуть на пример, вот так выглядит приложение без использования стилей:

Простое окно без применения стилей

А вот так оно может выглядеть:

То же окно с применением некоторых стилей

Результат, как говорится, налицо! На самом деле возможности WPF на этом не заканчиваются, но я не отличаюсь великими дизайнерскими навыками.

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

Рассмотрим, как этого можно добиться (Исходный код приложения можно найти на Github-е).

Для начала создадим словарь рессурсов стилей (на самом деле это не обязательно, если проект не большой и использует только одну форму, но скажем так - это Best Practice, позже будет проще использовать его повторно в других проектах). Для этого нужно создать папку Theme (опять же название совсем не критично, можно назвать папку как угодно, либо же вовсе файлы разместить в корне проекта, но стоит соблюдать порядок и названия элементов должно говорить о назначении элемента) в корне проекта. И в этой папке создадим xaml-файл с именем TextControls.xaml и содержанием:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StyledApp.Theme">

<Style x:Key="UIForValidationForm">
<Setter Property="Margin" Value="5,5,5,15"/>
</Style>

<!-- TextBlock -->
<Style TargetType="TextBlock" x:Key="TextBlockForValidationForm" BasedOn="{StaticResource UIForValidationForm}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>

<!-- TextBlock Left Aligned -->
<Style TargetType="TextBlock" x:Key="LeftAlignedTextBlockForValidationForm" BasedOn="{StaticResource TextBlockForValidationForm}">
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>

<!-- TextBox -->
<Style TargetType="TextBox" x:Key="TextBoxWithValidation" BasedOn="{StaticResource UIForValidationForm}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="#FFEBFAFF" />
<Setter Property="BorderBrush" Value="#FF64B5F6" />
<Setter Property="Padding" Value="4" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="root" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" SnapsToDevicePixels="true">
<Border x:Name="Background" BorderThickness="0,0,0,1" CornerRadius="3" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"/>
<ScrollViewer x:Name="PART_ContentHost"
Padding="{TemplateBinding Padding}"
BorderThickness="0"
IsTabStop="False"
Background="{x:Null}"
TextElement.Foreground="{TemplateBinding Foreground}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="#FFE3F2FD"/>
<Setter Property="BorderBrush" Value="#64B5F6"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#F5F5F5"/>
<Setter Property="BorderBrush" Value="#9E9E9E"/>
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Foreground" Value="#606060"/>
<Setter Property="Background" Value="#F5F5F5"/>
<Setter Property="BorderBrush" Value="#9E9E9E"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="#FFEBEE"/>
<Setter Property="BorderBrush" Value="#F44336"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder/>
<TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red" FontSize="11"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

В этом файле мы описали несколько стилей для некоего абстрактного родительского элемента (UIForValidationForm), элементов TextBlock и TextBox, последние в свою очередь наследуются от самого первого в списке элемента - UIForValidationForm. UIForValidationForm задает общие настройки Margin для всех остальных элементов. Стиль с названием TextBlockForValidationForm - задает параметры для текстового блока с позиционированием по правой границе. LeftAlignedTextBlockForValidationForm наследует настройки от TextBlockForValidationForm и переопределяет параметр позиционирования - по левой стороне.

Теперь, подключим этот файл к проекту. Для этого пропишем путь к нему в файле app.xaml:

<Application x:Class="StyledApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StyledApp"
StartupUri="/StyledApp;component/Views/EditUserView.xaml">
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries >
<ResourceDictionary Source="Theme/TextControls.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application> 

Здесь в секции ResourceDictionary.MergedDictionaries перечислим все файлы со стилями, которые мы хотим добавить в проект. В данном примере указан только один файл Theme/TextControls.xaml.

Давайте более подробно рассмотрим, что происходит в этих файлах и как работают стили.

Тэг Style

Файл TextControls.xaml разделен на несколько секций с помощью тегов <Style></Style>, этими тэгами отмечаются начало и конец описания одного стиля. В нашем файле указано 4 стиля.

Атрибут TargetType указывает к какому типу элементов данный стиль применим. Если мы хотим написать кастомный стиль для текстовой метки, то в этом атрибуте указываем Label.

Атрибут BasedOn - стиль, от которого наследуется описываемый стиль. Наследование возможно только от одного стиля.

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

Тег Setter

Внутри тэгов <Style></Style> указывается один или несколько тегов <Setter></Setter>. С помощью этих тегов задаются значения конкретным свойствам элемента. Атрибут Property указывает на название свойства, а Value - новое значение. Например в следующем коде:

<Style TargetType="TextBlock" x:Key="TextBlockForValidationForm" BasedOn="{StaticResource UIForValidationForm}">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>

Мы задаем новые значения свойствам:

  • VerticatAligment = Center - вертикальное позиционирование компонента по центру;
  • HorizontalAligment = Right - горизонтальное позиционирование компонента по правой границе;
  • TextWrapping = Wrap - включение переноса текста, если строка выходит за границы родительского компонента.

To be continued...

1 1 1 1 1 1 1 1 1 1 Рейтинг 100%

Печать E-mail

Добавить комментарий


Защитный код
Обновить