Ресурсы и стили. Использование менеджера визуальных состояний (Visual State Manager)

Элементы управления .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  NormalDisabledFocused и PointerOver
CarouselView DefaultItemCurrentItemPreviousItem и NextItem
Button (информация об элементе) Pressed
CheckBox (информация об элементе) IsChecked
CollectionView Selected
ImageButton (информация об элементе) Pressed
RadioButton (информация об элементе) Checked (элемент выбран) и Unchecked (элемент не выбран)
Switch (информация об элементе) On (включено) и Off(выключено)

Это означает, например, что так как кнопка Button — это наследник VisualElement, то для этого элементу управления мы можем использовать по умолчанию следующие состояния: NormalDisabledFocusedPointerOver и 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 и т.д. Также мы можем определять собственные состояния элементов управления и применять их.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии