#c# #wpf #data-binding #binding
#c# #wpf #привязка данных #привязка
Вопрос:
У меня есть небольшое приложение, в котором у меня есть текстовое поле, привязанное к модели через MVVM:
Моя модель:
public class MyModel : INotifyPropertyChanged
{
private double _myValue = 0;
public event PropertyChangedEventHandler PropertyChanged;
public double MyValue
{
get => _myValue;
set
{
if(value != _myValue)
{
if (value == 4)
throw new InvalidOperationException();
_myValue = value;
OnPropertyChanged();
}
}
}
/// <summary>
/// Called when a property was changed.
/// </summary>
/// <param name="propertyName">Name of the affected property.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Мой взгляд выглядит так:
<Window x:Class="ValidationTests.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:ValidationTests"
mc:Ignorable="d"
Title="MainWindow" Height="201.696" Width="322.679">
<Window.Resources>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding MyValue, Mode=TwoWay, ValidatesOnExceptions=True}"
HorizontalAlignment="Center" Width="150" VerticalAlignment="Center"/>
<Button Grid.Row="1" HorizontalAlignment="Center" Width="100" VerticalAlignment="Center" Height="30" Content="Test"/>
</Grid>
</Window>
Теперь я хочу сосредоточиться на текстовом поле при возникновении ошибки проверки. Как я могу этого добиться? Возможно ли это с помощью стиля?
Комментарии:
1. Изучите реализацию
IDataErrorInfo
интерфейса для обработки этих вещей; зачем вводитьInvalidOperationException
неправильное значение, обрабатывайте их изящно.2. Создание исключений в установщиках свойств по причинам проверки — это прекрасно
Ответ №1:
Если вы хотите предотвратить потерю фокуса клавиатуры до тех пор, пока TextBox
не будет указано допустимое значение, вы можете обработать PreviewLostKeyboardFocus
событие либо с помощью подключенного поведения, либо непосредственно в представлении:
private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) =>
e.Handled = Validation.GetHasError((TextBox)sender);
Вы также должны установить значение UpdateSourceTrigger
PropertyChanged
для выполнения проверки до того, как фокус будет потерян:
<TextBox Text="{Binding MyValue, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"
HorizontalAlignment="Center" Width="150" VerticalAlignment="Center"
PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus"/>
Вы не можете реализовать это в чистом XAML, используя a Style
или что-то еще.