Wpf MVVM, как отключить команду на основе ошибки при сбое преобразования с помощью iNotifydataerrorinfo через viewmodel?
Всем привет,
У меня есть класс ValidatableBindableBase, который реализует интерфейс INotifyDataErrorInfo и интерфейс INotifyPropertyChanged.
Проверки, зависящие от аннотаций данных и пользовательских проверок, работают нормально.
Проблема заключается в том, что когда текстовое поле не преобразует входные данные в тип данных связанного свойства, отображается сообщение об ошибке "не удалось преобразовать из строки 'ab' в целое число", но ошибки viewmodel не обновляются с этой ошибкой, и поэтому команда, которая должна быть отключена при ошибке, не отключается..
Моя главная цель-отключить команду при возникновении ошибки преобразования, и я хочу сделать это из viewmodel, если это возможно
Команда can-execute (которая определяет, включена кнопка или нет), этот метод зависит от коллекции ошибок модели представления,
когда возникает исключение преобразования (например, когда вы вводите текст в текстовое поле, привязанное к deciaml), коллекция ошибок не затрагивается (поскольку установщик свойств никогда не вызывается), и, следовательно, can execute команды не возвращает false..
код:
Public Class BindableBase Implements INotifyPropertyChanged Protected Overridable Sub SetProperty(Of T)(ByRef member As T, ByVal val As T, <CallerMemberName> Optional propertyName As String = Nothing) If Object.Equals(member, val) Then Return member = val RaisePropertyChanged(propertyName) End Sub Sub RaisePropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged End Class
Public Class ValidatableBindableBase Inherits BindableBase Implements INotifyDataErrorInfo Private _errors As New Dictionary(Of String, List(Of String)) Public ReadOnly Property HasErrors As Boolean Implements INotifyDataErrorInfo.HasErrors Get Return _errors.Count > 0 End Get End Property Public Event ErrorsChanged As EventHandler(Of DataErrorsChangedEventArgs) Implements INotifyDataErrorInfo.ErrorsChanged Public Function GetErrors(propertyName As String) As IEnumerable Implements INotifyDataErrorInfo.GetErrors If propertyName Is Nothing Then Return Nothing If _errors.ContainsKey(propertyName) Then Return _errors(propertyName) Else Return Nothing End If End Function Protected Overrides Sub SetProperty(Of T)(ByRef member As T, val As T, <CallerMemberName> Optional propertyName As String = Nothing) MyBase.SetProperty(member, val, propertyName) ClearErrors(propertyName) ValidateDataAnnotationsForProperty(propertyName, val) ValidateCustomErrors(propertyName) End Sub Private Sub ValidateDataAnnotationsForProperty(Of T)(ByVal propertyName As String, ByVal value As T) Dim results As New List(Of ValidationResult) Dim context As New ValidationContext(Me) context.MemberName = propertyName Validator.TryValidateProperty(value, context, results) If results.Any() Then _errors(propertyName) = results.Select(Function(r) r.ErrorMessage).ToList() Else _errors.Remove(propertyName) End If RaiseErrorsChanged(propertyName) End Sub Sub RaiseErrorsChanged(ByVal propertyName As String) RaiseEvent ErrorsChanged(Me, New DataErrorsChangedEventArgs(propertyName)) End Sub Private Sub ValidateCustomErrors(ByVal propertyName As String) Dim errors = ValidateProperty(propertyName) If errors IsNot Nothing Then For Each e In errors AddError(propertyName, e) Next End If End Sub Protected Sub AddError(ByVal propertyName As String, ByVal err As String) If Not _errors.ContainsKey(propertyName) Then _errors(propertyName) = New List(Of String) If Not _errors(propertyName).Contains(err) Then _errors(propertyName).Add(err) RaiseErrorsChanged(propertyName) End If End Sub Protected Sub ClearErrors(ByVal propertyName As String) If _errors.ContainsKey(propertyName) Then _errors.Remove(propertyName) RaiseErrorsChanged(propertyName) End If End Sub Protected Overridable Function ValidateProperty(ByVal propertyName As String) As IEnumerable(Of String) Return Nothing End Function End Class
и это свойство из ViewModel характерными validatableBindableBase:
Private _price As Decimal <Required(ErrorMessage:="سعر الصنف لا يمكن أن يكون فارغا")> <Range(0.0, Double.MaxValue, ErrorMessage:="سعر الصنف لا يمكن أن يكون سالبا")> Public Property Price As Decimal Get Return _price End Get Set(value As Decimal) SetProperty(_price, value) End Set End Property
Что я уже пробовал:
Здесь есть предлагаемое решение:
Проверки в WPF[^]
но он использует логику проверки в представлении, мне нужно сделать всю проверку в viewmodel, если это возможно.
а также, когда я попробовал это сделать, он изменил только сообщение, показанное под текстовым полем (я использую шаблон ошибки), но также не сделал команду, которая должна быть отключена при отключении ошибки..