Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Background" Value="Pink" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Запустите приложение и создайте условие для ошибки. Результат будет подобен тому, что показан на рис. 28.6, и укомплектован всплывающей подсказкой с сообщением об ошибке.
Определенный выше стиль изменяет внешний вид любого элемента управления TextBox, который содержит ошибку. Далее мы создадим специальный шаблон элемента управления с целью обновления свойства ErrorTemplate класса Validation, чтобы отобразить восклицательный знак красного цвета и установить всплывающие подсказки для восклицательного знака. Шаблон ErrorTemplate является декоратором, который располагается поверх элемента управления. Хотя только что созданный стиль обновляет сам элемент управления, шаблон ErrorTemplate будет размещаться поверх элемента управления.
Поместите элемент Setter непосредственно после закрывающего дескриптора Style.Triggers внутри созданного стиля. Вы будете создавать шаблон элемента управления, состоящий из элемента TextBlock (для отображения восклицательного знака) и элемента BorderBrush, который окружает TextBox, содержащий сообщение об ошибке (или несколько сообщений). В языке XAML предусмотрен специальный дескриптор для элемента управления, декорированного с помощью ErrorTemplate, под названием AdornedElementPlaceholder. Добавляя имя такого элемента управления, можно получить доступ к ошибкам, которые ассоциированы с элементом управления. В рассматриваемом примере вас интересует доступ к свойству Validation.Errors с целью получения ErrorContent (как делалось в Style.Trigger). Вот полная разметка для элемента Setter:
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock Foreground="Red" FontSize="20" Text="!"
ToolTip="{Binding ElementName=controlWithError,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="controlWithError" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
Запустите приложение и создайте условие для возникновения ошибки. Результат будет подобен представленному на рис. 28.7.
Итоговые сведения о проверке достоверности
На этом исследование методов проверки достоверности в WPF завершено. Разумеется, с их помощью можно делать намного большее. За дополнительными сведениями обращайтесь в документацию по WPF.
Создание специальных команд
Как и в разделе, посвященном проверке достоверности, можете продолжить работу с тем же проектом или создать новый проект и скопировать в него весь код из предыдущего проекта. Вы создадите новый проект по имени WpfCommands. В случае работы с проектом из предыдущего раздела обращайте внимание на пространства имен в примерах кода и корректируйте их по мере необходимости.
В главе 25 объяснялось, что команды являются неотъемлемой частью WPF. Команды могут привязываться к элементам управления WPF (таким как Button и MenuItem) для обработки пользовательских событий, подобных щелчку. Вместо создания обработчика события напрямую и помещения его кода в файл отделенного кода при возникновении события выполняется метод Execute() команды. Метод CanExecute() используется для включения или отключения элемента управления на основе специального кода. В дополнение к встроенным командам, которые применялись в главе 25, можно создавать собственные команды, реализуя интерфейс ICommand. Когда вместо обработчиков событий используются команды, появляются преимущества инкапсуляции кода приложения, а также автоматического включения и отключения элементов управления с помощью бизнес-логики.
Реализация интерфейса ICommand
Как было показано в главе 25, интерфейс ICommand определен следующим образом:
public interface ICommand
{
event EventHandler CanExecuteChanged;
bool CanExecute(object parameter);
void Execute(object parameter);
}
Добавление класса ChangeColorCommand
Обработчики событий для элементов управления Button вы замените командами, начав с кнопки Change Color. Создайте в проекте новую папку по имени Cmds. Добавьте в нее новый файл класса ChangeColorCornmand.cs. Сделайте класс открытым и реализующим интерфейс ICommand. Добавьте приведенные ниже операторы using (первый может варьироваться в зависимости от того, создавался ли новый проект для данного примера):
using WpfCommands.Models;
using System.Windows.Input;
Код класса должен выглядеть примерно так:
public class ChangeColorCommand : ICommand
{
public bool CanExecute(object parameter)
{
throw new NotImplementedException();
}
public void Execute(object parameter)
{
throw new NotImplementedException();
}
public event EventHandler CanExecuteChanged;
}
Если метод CanExecute() возвращает true, то привязанные элементы управления будут включенными, а если false, тогда они будут отключенными. Если элемент управления включен (CanExecute() возвращает true)и на нем совершается щелчок, то запустится метод Execute(). Параметры, передаваемые обоим методам, поступают из пользовательского интерфейса и основаны на свойстве CommandParameter, устанавливаемом в конструкциях привязки. Событие CanExecuteChanged предусмотрено в системе привязки и уведомлений для информирования пользовательского интерфейса о том, что результат, возвращаемый методом CanExecute(), изменился (почти как событие PropertyChanged).
В текущем примере кнопка Change Color должна работать, только если параметр отличается от null ипринадлежит типу Car. Модифицируйте метод CanExecute() следующим образом:
public bool CanExecute(object parameter)
=> (parameter as Car) != null;
Значение параметра для метода Execute() будет таким же, как и для метода CanExecute(). Поскольку метод Execute() может выполняться лишь в случае, если object имеет тип Car, аргумент потребуется привести к типу Car и затем обновить значение цвета:
public void Execute(object parameter)
{
((Car)parameter).Color="Pink";
}
Присоединение команды к CommandManager
Финальное обновление класса команды связано с присоединением команды к диспетчеру команд (CommandManager). Метод CanExecute() запускается при загрузке окна в первый раз и затем