INotifyDataErrorInfo ErrorsChanged не работает для элемента пользовательского интерфейса, связанного с ListCollectionView - PullRequest
0 голосов
/ 15 ноября 2018

Этот элемент 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 в модели, а не в ViewModel, но для различныхпричины, по которым я хочу, чтобы реализация была в ViewModel.

Вопрос

Какой формат имени свойства мне нужно использовать при настройке DataErrorsChangedEventArgs и при запуске ErrorsChanged?Или у меня есть какая-то другая структурная проблема?

1 Ответ

0 голосов
/ 18 ноября 2018

Я пришел к выводу, что вы не можете заставить INotifyDataErrorInfo взаимодействовать с пользовательским интерфейсом при использовании свойства ListCollectionView в вашей модели представления и при запуске ErrorsChanged из модели представления. Чтобы заставить это работать, поэтому у меня есть:

  • В модели (POCO) - Реализован INotifyDataError. Включен public RaiseErrorsChanged метод, который позволяет передавать имя свойства и список ошибок. Это добавляет ошибки в словарь ошибок и затем запускает ErrorsChanged.
  • В модели представления - подписано на событие PropertyChanged для каждого объекта планера в ListCollectionView. В обработчике событий PropertyChanged я выполняю проверку и затем вызываю метод RaiseErrorsChanged планера с любыми деталями ошибки.

Это исключает возможность проверки на заказ, и все хорошо.

...