Триггер данных срабатывает, когда привязанные к триггеру данные соответствуют определенному условию. В этом типе триггеров используется привязка.
Триггеры данных
Если триггер свойств отслеживает свойства элемента, к которому он применен, то триггер данных, благодаря привязке, может отслеживать внешний объект и срабатывать при выполнении определенных условий. Триггеры данных определяются с помощью объекта DataTrigger. Рассмотрим следующий пример:
<Entry x:Name="entry" Placeholder="Этот триггер отключит кнопку, если длина текста будет равна нулю"/>
<Button Text="Отправить">
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding x:DataType='Entry', Source={x:Reference entry}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
</Button.Triggers>
</Button>
</VerticalStackLayout>
Здесь DataTrigger применяется к кнопке Button (это элемент, который меняет свой внешний вид) и отслеживает свойство Text.Length у элемента Entry (это объект данных у которого отслеживается состояние)
Триггер можно прочитать так: если у элемента Entry с именем entry свойство Text.Length = 0, то свойство IsEnabled необходимо установить в значение false. При запуске приложения кнопка будет активна, несмотря на то, что Entry будет по умолчанию пустой:
Если написать что-то в Entry и потом удалить — сработает триггер данных:
Отслеживание произвольного объекта
Благодаря механизму привязки, DataTrigger может реагировать не только на изменение свойств каких-то визуальных элементов управления, но и на изменение свойств вообще любых объектов, к которым можно сделать привязку. Например, воспользуемся классом из части про интерфейс INotifyPropertyChanged. Вот как он выглядел:
public class Project : INotifyPropertyChanged
{
string name = "";
bool isActive = false;
double cost = 0;
public string Name {
get => name;
set
{
if (name != value)
{
name = value;
OnPropertyChanged();
}
}
}
public bool IsActive {
get => isActive;
set {
if (isActive != value)
{
isActive = value;
OnPropertyChanged();
}
}
}
public double Cost
{
get => cost;
set {
if (cost != value)
{
cost = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
Пусть наш триггер данных будет отключать кнопку, если свойство Name у объекта Project будет пустым. Перепишем наш пример следующим образом:
<?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="MauiApp17.MainPage"
xmlns:local="clr-namespace:MauiApp17">
<ContentPage.Resources>
<ResourceDictionary>
<local:Project x:Key="project" IsActive="True" Name="Проект" Cost="0"/>
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView>
<VerticalStackLayout
Padding="30,0"
Spacing="25">
<Entry Text="{Binding Source={StaticResource project}, Path=Name}"/>
<Button Text="Отправить">
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding x:DataType='Project', Source={StaticResource project}, Path=Name.Length}" Value="0">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
</Button.Triggers>
</Button>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Теперь текст элемента Entry привязан к свойству нашего объекта типа Project, а триггер — к длине текста свойства Name. Можно запустить приложение и убедиться, что триггер срабатывает как только мы удаляем из Entry текст и, следовательно, обнуляем длину текста у свойства объекта Project.
Итого
Триггеры данных в .NET MAUI позволяют менять внешний вид элементов управления в зависимости от изменения свойств других объектов. Для настройки триггера используется привязка, что позволяет использовать для отслеживания объекты произвольных типов данных.