Содержание
Элементы управления .NET MAUI могут находится в различных состояниях. например, кнопка может быть нажата или отключена, поле ввода может иметь фокус и так далее. При необходимости, мы можем менять оформление элемента управления в зависимости от его состояния. Для этого в .NET MAUI используется Visual State Manager (менеджер визуальных состояний)
Общие состояния элементов
Менеджер визуальных состояний определяет специальную группу с названием CommonStates
для состояний в которых могут находиться элементы управления, производные от VisualElement
. К этом состояниям относятся:
Normal
Disabled
Focused
Selected
PointerOver
Эти состояния являются взаимоисключающими. То есть в любое время только одно состояние может быть текущим (активным), например, кнопка не может быть одновременно в состояниях Normal
и Disabled
. Рассмотрим как мы можем менять внешний вид элемента управления в зависимости от его состояния.
Определение визуальных состояний в элементе управления
Рассмотрим как использовать менеджер визуальных состояний на примере обычной кнопки Button
. Создайте новый проект .NET MAUI и измените код MainPage.xaml следующим образом:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Vsm.MainPage"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Button Text="Click me" SemanticProperties.Hint="Counts the number of times you click" HorizontalOptions="Fill" > <VisualStateManager.VisualStateGroups> <VisualStateGroupList> <VisualStateGroup Name="CommonStates"> <VisualState Name="Normal"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="Lime" /> </VisualState.Setters> </VisualState> <VisualState Name="PointerOver"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightBlue" /> <Setter Property="BorderWidth" Value="3"/> <Setter Property="BorderColor" Value="DarkBlue"/> </VisualState.Setters> </VisualState> <VisualState Name="Pressed"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightCoral" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </VisualStateManager.VisualStateGroups> </Button> </VerticalStackLayout> </ScrollView> </ContentPage>
Рассмотрим этот код подробно. Итак, чтобы определить визуальные состояния элемента мы используем присоединенное свойство VisualStateManager.VisualStateGroups
.
<VisualStateManager.VisualStateGroups> тут прочий код </VisualStateManager.VisualStateGroups>
Это свойство представляет из себя коллекцию VisualStateGroupList
, которая должна содержать объекты VisualStateGroup
. В этой коллекции мы определяем новую группу визуальных состояний с именем CommonStates
:
<VisualStateManager.VisualStateGroups> <VisualStateGroupList> <VisualStateGroup Name="CommonStates"> //тут прочий код </VisualStateGroup> </VisualStateGroupList> </VisualStateManager.VisualStateGroups>
Внутри этой группы мы определяем три состояния для кнопки — Normal
, PointerOver
и Pressed
, то есть для кнопки в обычном состоянии, когда над кнопкой находится курсор мыши и когда кнопка нажата. Каждое из состояний представляет из себя объект типа VisualState
с именем равным имени состояния. Содержимое объекта — список объектов Setter
(как и у стилей) в которых мы определяем значения для каких-либо визуальных свойств элемента управления. Так, например, когда над кнопкой находится курсор мыши, то мы устанавливаем значения трех свойств:
<VisualState Name="PointerOver"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightBlue" /> <Setter Property="BorderWidth" Value="3"/> <Setter Property="BorderColor" Value="DarkBlue"/> </VisualState.Setters> </VisualState>
Проверим работу приложения. Так будет выглядеть наша кнопка при запуске приложения
при наведении курсора мышипри нажатии на кнопку
Определение визуальных состояний в стиле
Визуальные состояния можно определять непосредственно в стилях элементов. Перепишем наш пример с использованием стиля для кнопки:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Vsm.MainPage"> <ContentPage.Resources> <ResourceDictionary> <Style TargetType="Button"> <Setter Property="VisualStateManager.VisualStateGroups"> <VisualStateGroupList> <VisualStateGroup Name="CommonStates"> <VisualState Name="Normal"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="Lime" /> </VisualState.Setters> </VisualState> <VisualState Name="PointerOver"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightBlue" /> <Setter Property="BorderWidth" Value="3"/> <Setter Property="BorderColor" Value="DarkBlue"/> </VisualState.Setters> </VisualState> <VisualState Name="Pressed"> <VisualState.Setters> <Setter Property="BackgroundColor" Value="LightCoral" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </Setter> </Style> </ResourceDictionary> </ContentPage.Resources> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Button Text="Click me" HorizontalOptions="Fill" > </Button> </VerticalStackLayout> </ScrollView> </ContentPage>
Если посмотреть на этот пример внимательно, то можно заметить, что в стиле мы вместо свойства VisualStateManager.VisualStateGroups
использовали объект типа Setter в котором и указали свойство менеджера визуальных состояний
<Setter Property="VisualStateManager.VisualStateGroups">
В остальном же код остался неизменным. Можно запустить приложение и убедиться, что кнопка также реагирует изменением своего внешнего вида на три состояния.
Визуальные состояния доступные по умолчанию в .NET MAUI
Ниже представлены доступные по умолчанию визуальные состояния в .NET MAUI для различных элементов управления:
Элемент управления | Доступные состояния |
VisualElement |
Normal , Disabled , Focused и PointerOver |
CarouselView |
DefaultItem , CurrentItem , PreviousItem и NextItem |
(информация об элементе) |
Pressed |
CheckBox (информация об элементе) |
IsChecked |
CollectionView |
Selected |
ImageButton (информация об элементе) |
Pressed |
RadioButton (информация об элементе) |
Checked (элемент выбран) и Unchecked (элемент не выбран) |
Switch (информация об элементе) |
On (включено) и Off (выключено) |
Это означает, например, что так как кнопка Button
— это наследник VisualElement
, то для этого элементу управления мы можем использовать по умолчанию следующие состояния: Normal
, Disabled
, Focused
, PointerOver
и Pressed
.
Определение собственных состояний элемента
При необходимости, мы можем определять свои визуальные состояния элементов управления. Например, мы можем определить визуальное состояние элемента Entry
в зависимости от введенного пользователем значения. Для активации визуального состояния элемента мы должны в каком-либо месте кода C# сделать возов следующего метода:
public static bool GoToState(FrameworkElement control, string stateName);
Первый параметр — элемент управления к которому необходимо применить визуальное состояние, а второй — имя состояния (чувствительно к регистру).
Например, напишем следующий код страницы MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Vsm.MainPage"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Entry x:Name="NumberOnly" TextChanged="Entry_TextChanged"> <VisualStateManager.VisualStateGroups> <VisualStateGroupList> <VisualStateGroup Name="EntryStates"> <VisualState Name="Valid"> <VisualState.Setters> <Setter Property="Background" Value="LightGreen" /> <Setter Property="TextColor" Value="DarkGreen"/> </VisualState.Setters> </VisualState> <VisualState Name="Invalid"> <VisualState.Setters> <Setter Property="Background" Value="LightCoral" /> <Setter Property="TextColor" Value="DarkRed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </VisualStateManager.VisualStateGroups> </Entry> </VerticalStackLayout> </ScrollView> </ContentPage>
Здесь мы определили элемент Entry
(текстовое поле) у которого определили два состояния — Valid
и Invalid
. У текстового поля определен обработчик события TextChanged
, который выглядит следующим образом:
private void Entry_TextChanged(object sender, TextChangedEventArgs e) { if (int.TryParse(e.NewTextValue, out int value)) { if (VisualStateManager.GoToState(NumberOnly, "Valid") == false) throw new Exception("Error"); } else { VisualStateManager.GoToState(NumberOnly, "Invalid"); } }
Здесь мы проверяем, что ввел пользователь — целое число или просто строку и в зависимости от этого выбираем то или иное состояние. В работающем приложении компонент будет выглядеть следующим образом:
при вводе числапри вводе строки
Итого
Использование менеджера визуальных состояний (Visual State Manager) позволяет определить стиль оформления элемента в зависимости от того в каком состоянии он находится. В .NET MAUI предусмотрены стандартные состояния элементов, например, Focused
, Disabled
и т.д. Также мы можем определять собственные состояния элементов управления и применять их.