InvalidCastException при вызове PropertyChangedEventHandler - PullRequest
0 голосов
/ 17 марта 2020

Ситуация :

  • Приложение UWP, использующее MVVM и Xaml для пользовательского интерфейса
  • Модели представления получены из класса ModelBase, реализующего интерфейс INotifyPropertyChanged

Проблема :

  • при выполнении указанного c теста пользовательского интерфейса с использованием затронутого класса, в некоторых случаях приложение выдает InvalidCastException во время звонка PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)). Свойство propertyName установлено правильно с помощью [CallerMemberName], которое было проверено с помощью записи в журнале отладки. Метод SetProperty вызывается в DependencyProperty с полем поддержки. DebugConverter, используемый в элементе Xaml, который связан с событием PropertyChanged, показывает допустимое преобразование, но установка связанного элемента завершается неудачно. Похоже, что двойное удвоение невозможно, что не имеет смысла.

Вопрос

  • У кого-нибудь есть идея, в чем причина это исключение может быть?

Код

Control.xaml

Maximum="{Binding TimeControlCanvasWidth, Converter={StaticResource DebugConverter}}" />

ModelBase.cs

public class ModelBase : INotifyPropertyChanged
{
    /// <summary>
    /// The event raised, when the property changed
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        try
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        catch (System.InvalidCastException)
        {
            LogManager.Current.GetLogger(GetType()).LogCritical(() => $"#####{nameof(OnPropertyChanged)}" +
                $" - InvalidCastException | propertyName={propertyName}");
        }
    }

    protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null)
    {
        if (field?.Equals(value) == true)
        {
            return false;
        }

        field = value;

        // ReSharper disable once ExplicitCallerInfoArgument
        OnPropertyChanged(propertyName);
        return true;
    }
}

}

ViewModel.cs

public class TimeControlViewModel : ModelBase 
{ 
    private double _timeControlCanvasWidth;

    public double TimeControlCanvasWidth
    {
        get => _timeControlCanvasWidth;
        set
        {
             if (SetProperty(ref _timeControlCanvasWidth, value))
             {
                // do sth.
             }
        }
    }
}
...