Содержание
При работе с интерфейсом приложения нам придётся часто использовать различные цвета и оттенки для элементов управления. В WPF и XAML, в частности, для этих целей используются специальные объекты — кисти (Brush), используя которые мы можем устанавливать цвета для отдельных свойств элементов, а также использовать в качестве заполнителей области элемента различные объекты и изображения. В этой части мы рассмотрим доступные нам Кисти в XAML
Свойства, определяющие цветовое оформление XAML-элементов
Для визуальных элементов являющихся наследниками типа Control доступны следующие свойства цвета:
| Свойство | Тип | Описание |
Background |
Brush |
Кисть, которая используется для заливки фона элемента управления. Значение по умолчанию — Transparent |
Foreground |
Кисть, которая заливает основной цвет элемента управления. По умолчанию используется цвет шрифта диалоговых окон системы. | |
BorderBrush |
Кисть, которая используется для заливки границы элемента управления. Значение по умолчанию — Transparent |
Все эти три свойства имеют один и тот же тип — Brush (кисть). При этом, в WPF и XAML нам доступны различные наследники этого типа, позволяющие делать как сплошную, так и. например, градиентную заливки.
Кисти в XAML
Иерархию объектов типа Brush можно представить в виде следующей схемы:
Рассмотрим различные кисти, которые мы можем использовать в наших приложениях WPF.
Кисть SolidColorBrush и цвет в XAML
Определяя цвет любого из представленных выше свойств, мы особо и не задумываемся над тем, что фактически используем объект типа SolidColorBrush, которые представляет кисть со сплошной заливкой. Нам достаточно использовать одно из зарезервированных названий цветов, например, Red, Blue, Green и т.д. или задать цвет в формате #FF00FFFF, чтобы получить заливку цветом како-либо части XAML-элемента. Вся работа по созданию необходимых объектов производится при обработке XAML-документа.
При этом стоит помнить, что любой цвет XAML представляется экземпляром структуры Color из пространства имен System.Windows.Media, которая описывает любой цвет или его оттенок с использованием четырех составляющих: непрозрачность цвета (A — альфа-канал), красный цвет (R), зеленый цвет (G) и синий цвет (B). Значение каждой составляющей изменяется в диапазоне от 0 до 255. Если составляющие R, G, B равны 0, то это соответствует черному цвету, если все три составляющие равны 255, то это соответствует белому цвету. Если значение альфа-канала (A) равно 255, то это соответствует полностью непрозрачному цвету, а 0 — полностью прозрачному (Transparent) и такой цвет невидим.
Если для задания цвета используется зарезервированное название, например, Red или используется шестнадцатеричное значение, состоящее из трех цифр, то такой цвет получает значение альфа-канала равное 255 и формируется полностью непрозрачный цвет.
Используя возможные способы задания цвета в XAML, мы можем, например, определить фон окна приложения следующими способами:
используя зарезервированное название цвета
<Window x:Class="WpfApp1.MainWindow"
...
Background="Blue">
</Window>
используя шестнадцатеричное определение цвета
<Window x:Class="WpfApp1.MainWindow"
...
Background="#0000FF">
</Window>
В любом случае, здесь никак не прослеживается то, что мы используем объект SolidColorBrush. Для того, чтобы иметь возможность явным образом определить и кисть и цвет в коде XAML мы должны использовать элементы свойств. Например, определим цвет фона окна следующим образом:
<Window x:Class="WpfApp1.MainWindow"
...
<Window.Background>
<SolidColorBrush>Blue</SolidColorBrush>
</Window.Background>
</Window>
Здесь мы использовали в качестве содержимого для элемента SolidColorBrush имя цвета — Blue. При необходимости, мы также можем определить каждый компонент цвета отдельно, например, так:
<Window x:Class="WpfApp1.MainWindow"
...
<Window.Background>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color R="#00" G="#00" B="#FF" A="#FF"/>
</SolidColorBrush.Color>
</SolidColorBrush>
</Window.Background>
</Window>
Или использовать десятичную систему счисления для задания свойств цвета:
<Window x:Class="WpfApp1.MainWindow"
...
<Window.Background>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color R="0" G="0" B="255" A="125"/>
</SolidColorBrush.Color>
</SolidColorBrush>
</Window.Background>
</Window>
В приведенных выше примерах мы явно определили объект SolidColorBrush у которого одним из свойств выступает свойство Color одноименного типа, которое мы также задаем, используя элемент свойства:
<Color R="0" G="0" B="255" A="125"/>
Более того, мы можем заменить декларацию свойства Color и таким вариантом:
<Window.Background>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color>
Blue
</Color>
</SolidColorBrush.Color>
</SolidColorBrush>
</Window.Background>
или использовать шестнадцатеричное определение цвета. Используя различные варианты определения цвета, кисти SolidColorBrush и свойства позиционирования элементов, мы можем создать, например, вот такой внешний вид окна:
<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">
<Grid>
<Label Content="XAML"
FontSize="96"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontFamily="Arial Black" FontWeight="Bold" Foreground="Red"/>
<Label Content="Это не WPF"
FontSize="80"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontFamily="Arial Black" FontWeight="Bold" >
<Label.Foreground>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color R="0" G="255" B="0" A="180"></Color>
</SolidColorBrush.Color>
</SolidColorBrush>
</Label.Foreground>
</Label>
</Grid>
</Window>
Здесь два элемента типа Label накладываются друг на друга и у одного из них для цвета текста применен цвет с альфа-каналом. В результате мы увидим следующий текст:
SolidColorBrush — это только один из наследников абстрактного класса Brush. Рассмотрим другие типы кистей, которые мы можем применить в WPF и XAML.
Кисти в XAML: LinearGradientBrush
Объект LinearGradientBrush представляет кисть для заливки с использованием линейного градиента (плавного перехода от одного цвета к другому). Тип LinearGradientBrush предоставляет нам следующие свойства:
| Свойство | Тип | Описание |
Gradient |
GradientStopCollection |
Коллекция объектов типа GradientStop, определяющих точки перехода градиента |
Start |
Point |
Начальная точка градиента. По умолчанию (0,0). |
End |
Point |
Конечная точка градиента. По умолчанию (1,1) |
Spread |
GradientSpreadMethod |
Тип метода рисования градиента. Может принимать следующие значения:
|
Opacity |
double |
Прозрачность |
Продемонстрируем использование этих свойств на примере. Для того, чтобы создать градиентную заливку, нам необходимо задать направление градиента, а также точки перехода в виде коллекции объектов GradientStop. По умолчанию направление градиента — диагональ. Например, используем линейный градиент для заливки окна приложения:
<Window x:Class="WpfApp1.MainWindow"
...>
<Window.Background>
<LinearGradientBrush>
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Green" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
</Window.Background>
</Window>
Здесь мы оставили направление градиента по умолчанию — от верхнего левого угла к нижнему правому и определили три точки перехода (три объекта GradientStop). У каждой точки мы указали цвет и значение Offset (смещение). Таким образом, наш градиент будет следующим: в точке Startцвет будет красным с плавным переходом в зеленый до точки (0.5, 0.5). В точке (0.5, 0.5) цвет зеленый с плавным переходом к синему. В точке (1,1) цвет синий. В результате мы увидим следующую заливку окна:
При желании, мы можем изменить направление градиента, например, вот так:
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Green" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
Теперь градиент будет горизонтальным — начинаться от середины левой границы и заканчиваться на середине правой границы:
Отдельное внимание стоит уделить такому свойству как Spread. Определим градиент следующим образом:
<LinearGradientBrush StartPoint="0,0.5" EndPoint="0.5,0.5">
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Green" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
Градиент теперь заканчивается на середине окна, а свойство Spread по умолчанию равно Pad, то есть, начиная с точки (0.5, 0.5) заливка формы будет определяться цветом на конце вектора градиента:
Значение Reflect повторяет градиент в обратном направлении:
а значение Repeat — в том же направлении:
Использовать градиент мы можем не только для свойства Background элемента, но и для любых других свойств с типом Brush, например, используем градиент для заливки рамки у кнопки:
<Button Width="400" Height="200" Content="Моя кнопка" BorderThickness="15">
<Button.BorderBrush>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="0.5,0.5" SpreadMethod="Reflect">
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Yellow" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</LinearGradientBrush>
</Button.BorderBrush>
</Button>
Кисти в XAML: RadialGradientBrush
Кисть RadialGradientBrush также, как и LinearGradientBrush закрашивает заданную область, используя градиент, но распространение цвета идёт во всех направлениях от точки начала градиента до границы эллипса градиента. У класса RadialGradientBrush определены следующие свойства:
| Свойство | Тип | Описание |
Gradient |
GradientStopCollection |
Коллекция объектов типа GradientStop, определяющих точки перехода градиента |
Spread |
GradientSpreadMethod |
Тип метода рисования градиента. Может принимать следующие значения:
|
Center |
Point |
Центр эллипса закрашиваемой области |
GradientOrigin |
Point |
Начало радиального градиента |
RadiusX |
double |
Горизонтальный радиус эллипса |
RadiusY |
double |
Вертикальный радиус эллипса |
Продемонстрируем действие новых для нас свойств на следующем примере:
<Window x:Class="WpfApp1.MainWindow"
...>
<Window.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Yellow" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</RadialGradientBrush>
</Window.Background>
</Window>
В результате, мы увидим градиент, распространяющийся из центра окна
Изменим положение внешнего эллипса для градиента:
<Window.Background>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.9,0.5" RadiusX="0.7" RadiusY="0.5">
<GradientStopCollection>
<GradientStop Color="Red" Offset="0"></GradientStop>
<GradientStop Color="Yellow" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1"></GradientStop>
</GradientStopCollection>
</RadialGradientBrush>
</Window.Background>
Кисти в XAML: ImageBrush
Кисть ImageBrush — это наследник класса TileBrush и заполняет область растровым изображением с предоставляет нам следующие свойства:
| Свойство | Тип | Описание |
Image |
ImageSource |
Изображение, которое используется для заполнения области |
Opacity |
double |
Степень прозрачности |
Stretch |
Stretch |
Определяет правила растягивания изображения и может принимать следующие значения: None, Uniform, UniformToFill, Fill |
Tile |
TileMode |
Определяет способ заполнения области и может принимать следующие значения: FlipX, FlipXY, FlipY, None, Tile |
Viewbox |
Rect |
Определяет прямоугольный фрагмент изображение, которое помещается на базовую плитку |
Viewport |
Rect |
Определяет расположение и размеры прямоугольника, который выделяется в области вывода для базовой плитки |
ViewportUnits |
BrushMappingMode |
Определяет относительность или абсолютность чисел, определяющих значения для Viewport |
Для демонстрации работы ImageBrush нам потребуется какое-либо изображение. Создайте в проекте папку Images и разместите в ней любое изображение. Например, я буду использовать вот такую картинку:
а структура проекта будет вот такой:
Теперь изменим код MainWindow.xaml следующим образом:
<Window x:Class="WpfApp1.MainWindow"
...>
<Window.Background>
<ImageBrush ImageSource="/images/wpf.png"></ImageBrush>
</Window.Background>
</Window>
В результате получим вот такой вид окна приложения:
В данном случае, свойство Stretch равно Fill — изображение растягивается, занимая всё доступное пространство области. Ниже представлено как будет выглядеть окно при различных вариантах свойства Stretch:
Stretch = "None". Изображение не растягивается
Stretch="Uniform". Изображение растягивается с сохранением пропорций:
Stretch="UniformToFill". Изображение растягивается с сохранением пропорций сторон, однако заполняет все доступное пространство области:
Если для ImageBrush необходимо использовать только часть изображения, то нам необходимо задать значения свойства Viewbox, которое представляет собой тип Rect. Для задания этого свойства нам необходимо определить координаты левого верхнего угла, а также длину и ширину прямоугольника. Все величины по умолчанию задаются в относительных единицах. Например, выделим только часть изображения и растянем его на всю доступную область с сохранением пропорций:
<Window.Background>
<ImageBrush
Viewbox="0.25, 0.1, 0.5,0.5"
Stretch="UniformToFill"
ImageSource="/images/wpf.png"></ImageBrush>
</Window.Background>
В результате получим вот такой вид окна:
Свойство Viewport используется в том случае, если нам необходимо «размножить» изображение для заполнения области. Например, изменим свойства ImageBrush следующим образом:
<Window.Background>
<ImageBrush
Viewbox="0.25, 0.1, 0.5,0.5"
Viewport="0,0,0.1,0.1"
TileMode="Tile"
Stretch="Uniform"
ImageSource="/images/wpf.png"></ImageBrush>
</Window.Background>
Теперь вся область окна будет заполнена отдельными фрагментами изображения, как показано на рисунке ниже:
Свойство TileMode может принимать следующие значения:
Кисти в XAML: DrawingBrush
Кисть DrawingBrush также, как и ImageBrush может применяться для заполнения области каким-либо изображением, но является более сложной в использовании, так как позволяет использовать не только изображения, но и различные геометрические фигуры, текст и т.д.
Класс DrawingBrush предоставляет нам следующее дополнительное (по сравнению с ImageBrush) свойство:
| Свойство | Тип | Описание |
Drawing |
Drawing |
Объект, описывающий содержимое кисти |
Сам по себе, класс Drawing является абстрактным, поэтому мы можем использовать только его наследников. Ниже представлены наследники класса Drawing и их описание
| Тип | Описание |
DrawingGroup |
Коллекция элементов типа Drawing, с которой можно работать как с одним изображением, то есть ко всем членам коллекции применяются одни и те же свойства |
GeometryDrawing |
Совокупность геометрических фигур, декларируемых свойством Geometry. Здесь используются одни и те же свойства Brush и Pen для всех фигур коллекции |
GliphRunDrawing |
Представляет текст в виде объекта типа GliphRun |
ImageDrawing |
Фрагмент графического изображения |
VideoDrawing |
Воспроизводит мультимедиа файл. Для видеофайла выполняет визуализацию в прямоугольнике, определенном свойством Rect |
Продемонстрируем один из примеров использования этой кисти в приложении WPF:
<Window x:Class="WpfApp1.MainWindow"
...>
<Window.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="LightBlue">
<GeometryDrawing.Geometry>
<GeometryGroup>
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="25,50" />
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="50,50" />
<EllipseGeometry RadiusX="12.5" RadiusY="25" Center="75,50" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="Gray" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Window.Background>
</Window>
Здесь мы используем три эллипса, чтобы заполнить область окна. При этом, для всех трех фигур используются одни и те же свойства заливки, толщины рамки и её цвета. В конструкторе окно будет выглядеть следующим образом:
Кисти в XAML: VisualBrush
Кисть VisualBrush использует в качестве заполнителя изображение какого-либо визуального элемента. Эта кисть предоставляет нам следующие свойства:
| Свойство | Тип | Описание |
AutoLayoutContent |
bool |
Указывает на соответствие экземпляра VisualBrush макету декларированного в нем объекта Visual |
Visual |
Visual |
Содержимое кисти |
Например, используем в качестве содержимого кисти кнопку:
<Window.Background>
<VisualBrush AutoLayoutContent="True" Stretch="Uniform">
<VisualBrush.Visual>
<Button Content="Hello, World"/>
</VisualBrush.Visual>
</VisualBrush>
</Window.Background>
В итоге, кнопка растянется на всё доступное пространство, сохранив при этом свои пропорции
Итого
Для визуального оформления элементов в XAML мы можем использовать такие свойства элементов как Background, Foreground и BorderBrush, каждое из которых представляется объектом Brush (кисть). В XAML и WPF мы можем использовать шесть различных типов кистей — SolidBrush, LinearGradientBrush, RadialGradientBrush, DrawingBrush, ImageBrush, VisualBrush.
















