Я использую правило проверки в TextBox для проверки строки ввода пользователя.Текст привязан к свойству float в модели представления, и механизм привязки WPF достаточно заинтересован, чтобы автоматически преобразовать строку в float для меня.
Однако, когда проверка не удалась, привязка, кажется, считывает обратностарое значениеЭто приводит к тому, что я получаю красную рамку вокруг текстового поля, даже если текст вернулся к последнему приемлемому значению с плавающей запятой.
Вопрос: Как убедиться, что неверный вводимый текст неавтоматически перезаписывается механизмом привязки при сбое проверки?Привязка должна быть двухсторонней.
Следует отметить, что я делаю небольшую хитрость в своем ValidationRule, где я позволяю ему находить текущую модель представления из локатора модели представления и использует подход INotifyDataErrorInfo впосмотреть модель.То, что я нашел отличным решением, так как это означает, что ViewModel HasError будет собирать все ошибки валидации для меня (и это позволит мне применять валидацию в правилах валидации или в модели представления при настройке свойства). Преимущество разрешения валидацииПравило применения проверки с использованием INotifyDataErrorInfo в модели представления заключается в том, что проверку можно применять перед автоматическим преобразованием из строки в число с плавающей точкой, гарантируя, что проверка выполняется даже тогда, когда пользователь вводит «Hello World», что приводит к исключению (поглощенномупривязка двигателя) во время автоматического преобразования в плаваниеЭто позволяет мне сохранять тип свойства с плавающей точкой в виртуальной машине и по-прежнему выполнять проверку.
XAML
<TextBox Grid.Row="2" Grid.Column="2" x:Name="txtPreHeight"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Center"
Template="{DynamicResource TextBoxBaseControlTemplateMainScreen}">
<TextBox.Text>
<Binding
Path="PreHeight"
ValidatesOnExceptions="False"
NotifyOnValidationError="True"
ValidatesOnNotifyDataErrors="True"
UpdateSourceTrigger="LostFocus"
>
<Binding.ValidationRules>
<validationrules:PreHeightValidationRule ViewModelType="GotoPositionViewModel" Min="0" Max="100" ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<i:Interaction.Triggers>
<helper:RoutedEventTrigger RoutedEvent="{x:Static Validation.ErrorEvent}">
<cmd:EventToCommand Command="{Binding SetFocusOnValidationErrorCommand}"
PassEventArgsToCommand="True" />
</helper:RoutedEventTrigger>
</i:Interaction.Triggers>
</TextBox>
ValidationRule
class PreHeightValidationRule : ValidationRule
{
private ValidationService validationService_;
private Int32 min_ = Int32.MaxValue;
private Int32 max_ = Int32.MinValue;
private string viewModelType_ = null;
public PreHeightValidationRule()
{
validationService_ = ServiceLocator.Current.GetInstance<Validation.ValidationService>();
}
public Int32 Min
{
get { return min_; }
set { min_ = value; }
}
public Int32 Max
{
get { return max_; }
set { max_ = value; }
}
public string ViewModelType
{
get { return viewModelType_; }
set { viewModelType_ = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo, BindingExpressionBase owner)
{
ValidationResult result = base.Validate(value, cultureInfo, owner);
ViewModel.ViewModelBaseWithNavigation vm;
System.Reflection.Assembly asm = typeof(ViewModelLocator).Assembly;
Type type = null;
if (type == null)
type = asm.GetType(ViewModelType);
if (type == null)
type = asm.GetType("TeachpendantControl.ViewModel." + ViewModelType);
vm = (ViewModel.ViewModelBaseWithNavigation)ServiceLocator.Current.GetInstance(type);
ICollection<string> validationErrors = new List<string>();
try
{
validationService_.ValidatePreHeight(value.ToString(), ref validationErrors, Min, Max);
}
catch (Exception e)
{
validationErrors.Add("Failed to validate, Exception thrown " + e.Message);
}
finally
{
vm.UpdateValidationForProperty(((BindingExpression)owner).ResolvedSourcePropertyName, validationErrors, validationErrors.Count == 0);
}
return new ValidationResult(validationErrors.Count == 0, validationErrors);
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
return new ValidationResult(false, null);
}
}