INotifyDataErrorInfo ErrorsChanged не работает для элемента пользовательского интерфейса, связанного с ListCollectionView
Этот элемент XAML привязан к ListCollectionView в моей модели представления:
<Style x:Key="ErrorStyle" TargetType="{x:Type Control}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Background" Value="Salmon"/>
</Trigger>
</Style.Triggers>
</Style>
...
<controls:AutoCompleteBox Grid.Column="1" Grid.Row="0" Margin="5" Height="20" Width="270" HorizontalAlignment="Left" VerticalAlignment="Center"
Name="typeName"
Style="{StaticResource ErrorStyle}"
Text="{Binding Path=AirframeCollectionView/TypeName, UpdateSourceTrigger=LostFocus, Mode=TwoWay,
ValidatesOnNotifyDataErrors=True,
NotifyOnValidationError=True,
ValidatesOnExceptions=True}"
ItemsSource="{Binding Path=TypeNames}"
IsTextCompletionEnabled="True"
FilterMode="Contains"
MinimumPrefixLength="3">
</controls:AutoCompleteBox>
ListCollectionView определяется следующим образом:
public ListCollectionView AirframeCollectionView
{
get
{
return this.airframeCollectionView;
}
set
{
this.airframeCollectionView = value;
this.RaisePropertyChanged("AirframeCollectionView");
}
}
и инициализируется:
this.currentAirframes = new ObservableCollection<Airframe>(this.UnitOfWork.Airframes.GetAirframesForRegistration(this.SearchRegistration));
this.AirframeCollectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(this.currentAirframes);
При проверке AirframeCollectionView/TypeName я использую интерфейс INotifyDataErrorInfo, следовательно:
private readonly Dictionary<string, ICollection<string>> validationErrors = new Dictionary<string, ICollection<string>>();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors
{
get { return this.validationErrors.Count > 0; }
}
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName) || !this.validationErrors.ContainsKey(propertyName))
{
return null;
}
return this.validationErrors[propertyName];
}
private void RaiseErrorsChanged(string propertyName)
{
if (this.ErrorsChanged != null)
{
this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
Чтобы вызвать ошибку, я делал это:
this.validationErrors["AirframeCollectionView/TypeName"] = validationErrors;
this.RaiseErrorsChanged("AirframeCollectionView/TypeName");
Это не вызывает ответ об ошибке в пользовательском интерфейсе. Я изменил имя свойства с "AirframeCollectionView/TypeName" на "TypeName", но это тоже не работает. В отладчике я подтвердил, что validationErrors загружается с ошибками и что ErrorsChanged запускается с указанным именем свойства.
Обратите внимание, что все это работало, когда я реализовал INotifyDataErrorInfo в модели, а не в View Model, но по разным причинам я хочу, чтобы реализация была во ViewModel.
Вопрос
Какой формат имени свойства я должен использовать при настройке DataErrorsChangedEventArgs и при запуске ErrorsChanged? Или у меня есть какая-то другая структурная проблема?
1 ответ
Я пришел к выводу, что вы не можете заставить INotifyDataErrorInfo взаимодействовать с пользовательским интерфейсом при использовании свойства ListCollectionView в вашей модели представления и при запуске ErrorsChanged из модели представления. Чтобы заставить это работать, поэтому у меня есть:
- В модели (POCO) - реализован INotifyDataError. Включен открытый метод RaiseErrorsChanged, который позволяет передавать имя свойства и список ошибок. Это добавляет ошибки в словарь ошибок, а затем запускает ErrorsChanged.
- В модели представления - подписано на событие PropertyChanged для каждого объекта Airframe в ListCollectionView. В обработчике события PropertyChanged я выполняю проверку и затем вызываю метод RaiseErrorsChanged планера с любыми деталями ошибки.
Это исключает возможность проверки на заказ, и все хорошо.