Исключения привязки данных

В приложении wpf у меня есть привязка данных: текстовое поле к свойству int и double с INPC.

Логика приложения должна использовать «PropertyChanged» в UpdateSourceTrigger. Также реализован интерфейс INotifyDataErrorInfo с атрибутами аннотаций данных.

Когда я очищаю текстовое поле, я вижу исключения привязки данных в окне вывода отладки.

System.Windows.Data Error: 7 : ConvertBack cannot convert value '' (type 'String'). BindingExpression:Path=Power; DataItem='Auto' (HashCode=64554036); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: Input string has invalid format.
   at System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
   at System.String.System.IConvertible.ToDouble(IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
   at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'

Я думаю, это нехорошо.

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

Насколько важно избегать этих исключений?

Должен ли он быть обернут в этом случае для модельного класса? Какова наилучшая практика для этого случая?

Мой пример кода с этой проблемой.

<TextBox Text="{Binding Power, UpdateSourceTrigger=PropertyChanged}"/>
public class Auto : INotifyPropertyChanged
    {
        string _model;
        private double _power;
        private int _volume;

        public event PropertyChangedEventHandler PropertyChanged;

        private void Set<T>(ref T field, T value, [CallerMemberName]string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public string Model
        {
            get => _model;
            set => Set(ref _model, value);
        }
        public double Power
        {
            get => _power;
            set => Set(ref _power, value);
        }
        public int Volume
        {
            get => _volume;
            set => Set(ref _volume, value);
        }
    }

person Noisy88    schedule 17.10.2019    source источник
comment
В идеале вы должны избегать любых таких исключений. Довольно часто приложение работает нормально, когда в окне визуальной студии появляется множество из них. Если ваше приложение работает нормально, то одна из распространенных стратегий — игнорировать их. Однако вы не можете обрабатывать исключения первого шанса.   -  person Andy    schedule 17.10.2019
comment
@Andy Я часто замечал, что многие приложения используют путь привязки к (Validation.Errors) [0] .Errors Content вместо (Validation.Errors) .CurrentItem.Content. Это вызовет исключение привязки данных. Но никого это не волнует. :)   -  person Noisy88    schedule 17.10.2019
comment
Ну да. Вы можете использовать косую черту для текущего элемента. Но это бесконечная история, потому что разработчики просто копируют это [0] в примерах, которые они находят в ответах, размещенных на этом веб-сайте стека wossname.   -  person Andy    schedule 18.10.2019


Ответы (1)


Насколько важно избегать этих исключений?

Не важно, так как фреймворк уже обрабатывает их за вас.

Должен ли он быть обернут в этом случае для модельного класса?

Нет, не используйте свойства string для хранения значений int и double.

Какова наилучшая практика для этого случая?

Либо игнорируйте ошибки привязки, либо реализуйте свои собственные преобразователи:

public class DoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!double.TryParse(value.ToString(), out double d))
            return Binding.DoNothing;
        return d;
    }
}

Использование:

<TextBox>
    <TextBox.Text>
        <Binding Path="Power" UpdateSourceTrigger="PropertyChanged">
            <Binding.Converter>
                <local:DoubleConverter />
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>
person mm8    schedule 18.10.2019