Подтвердить что ты не робот

Как обрабатывать исключение в преобразователе значений, чтобы можно было отобразить настраиваемое сообщение об ошибке

У меня есть текстовое поле, которое связано с классом с свойством типа Timespan и написало преобразователь значений для преобразования строки в TimeSpan.

Если в текстовое поле введено не число, я бы хотел, чтобы отображалось настраиваемое сообщение об ошибке (а не в строке ввода по умолчанию в неправильном формате).

Код конвертера:

    public object ConvertBack(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        try
        {
            int minutes = System.Convert.ToInt32(value);
            return new TimeSpan(0, minutes, 0);
        }
        catch
        {
            throw new FormatException("Please enter a number");
        }
    }

Я установил 'ValidatesOnExceptions = True' в привязке XAML.

Однако я столкнулся с следующей статьей MSDN, которая объясняет, почему приведенное выше не будет работать:

"Механизм привязки данных не использует исключения, которые генерирует пользовательский преобразователь. Любое исключение, которое вызывается методом Convert или любые неперехваченные исключения, которые генерируются методами, которые вызывает метод Convert, обрабатываются как ошибки времени выполнения"

Я читал, что "ValidatesOnExceptions действительно ломает исключения в TypeConverters, поэтому мои конкретные вопросы:

  • Когда вы используете TypeConverter над ValueConverter
  • Предполагая, что TypeConverter не является ответом на проблему выше, как я могу отобразить свое пользовательское сообщение об ошибке в пользовательском интерфейсе
4b9b3361

Ответ 1

Я использовал бы ValidationRule для этого, таким образом, конвертер может быть уверен, что преобразование работает, поскольку оно вызывается только в том случае, если проверка успешно, и вы можете использовать прикрепленное свойство Validation.Errors, которое будет содержать ошибки, созданные вашим ValidationRule, если вход не так, как вы хочу этого.

например. (обратите внимание на привязку всплывающей подсказки)

<TextBox>
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="Background" Value="Pink"/>
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
    <TextBox.Text>
        <Binding Path="Uri">
            <Binding.ValidationRules>
                <vr:UriValidationRule />
            </Binding.ValidationRules>
            <Binding.Converter>
                <vc:UriToStringConverter />
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>

screenshot

Ответ 2

Я использовал проверку и конвертер для принятия null и цифр

XAML:

<TextBox x:Name="HeightTextBox" Validation.Error="Validation_Error">
    <TextBox.Text>
        <Binding Path="Height"
                 UpdateSourceTrigger="PropertyChanged" 
                 ValidatesOnDataErrors="True"
                 NotifyOnValidationError="True"
                 Converter="{StaticResource NullableValueConverter}">
            <Binding.ValidationRules>
                <v:NumericFieldValidation />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Код за:

private void Validation_Error(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
        _noOfErrorsOnScreen++;
    else
        _noOfErrorsOnScreen--;
}

private void Confirm_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = _noOfErrorsOnScreen == 0;
    e.Handled = true;
}

ValidationRule:

public class NumericFieldValidation : ValidationRule
{
    private const string InvalidInput = "Please enter valid number!";

    // Implementing the abstract method in the Validation Rule class
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        float val;
        if (!string.IsNullOrEmpty((string)value))
        {
            // Validates weather Non numeric values are entered as the Age
            if (!float.TryParse(value.ToString(), out val))
            {
                return new ValidationResult(false, InvalidInput);
            }
        }

        return new ValidationResult(true, null);
    }
}

Конвертер:

public class NullableValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (string.IsNullOrEmpty(value.ToString()))
            return null;
        return value;
    }
}