Доступ к ошибкам проверки INotifyDataErrorInfo из шаблона ошибок XAML с использованием состава

#wpf #validation #xaml #binding #inotifydataerrorinfo

#wpf #проверка #xaml #привязка #inotifydataerrorinfo

Вопрос:

Мой базовый класс модели представления изначально реализовывал INotifyDataErrorInfo, и все работало безупречно, но сейчас я изучаю, как я мог бы выполнить проверку с использованием композиции, а не наследования, так что моему базовому классу модели представления не нужно делать ничего, кроме INotifyPropertyChanged . Я также ищу повторно используемое решение, поэтому мне не нужно внедрять INotifyDataErrorInfo во всех моих моделях представления.

Я создал конкретную реализацию INotifyDataErrorInfo, которую я могу включить в свои модели представления, требующие проверки (включен только соответствующий код):

 public class NotifyDataErrorInfo : INotifyDataErrorInfo
{
    public readonly Dictionary<string, string> ValidationErrorsByPropertyName = new Dictionary<string, string>();

    public IEnumerable GetErrors(string propertyName)
    {
        ...
    }

    public bool HasErrors { get; }
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
}
 

Когда MyViewModel обнаруживает ошибки проверки, он получает / устанавливает их через экземпляр объекта NotifyDataErrorInfo. (В моей оригинальной версии ViewModel реализовал INotifyDataErrorInfo. Это больше не так, поскольку я изучаю достижение тех же результатов с помощью composition.)

 public class MyViewModel : ViewModel
{
    public NotifyDataErrorInfo NotifyDataErrorInfo { get; } = new NotifyDataErrorInfo();
}
 

Вот текстовое поле, которое сообщает об ошибках проверки в установщике свойств MaxDaysText и задает шаблон ошибки проверки.

 <TextBox        
    Text="{Binding MaxDaysText, UpdateSourceTrigger=PropertyChanged}"
    Validation.ErrorTemplate="{StaticResource TextBoxValidationErrorTemplate}" />
 

Теперь мне нужно обновить шаблон ошибки проверки, чтобы получить доступ к ошибкам в свойстве NotifyDataErrorInfo, но я не уверен, как это сделать.

 <ControlTemplate x:Key="TextBoxValidationErrorTemplate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Border
            Grid.Row="0"
            HorizontalAlignment="Left"
            BorderBrush="{StaticResource ErrorMessageBorderBrush}"
            BorderThickness="1">
            <AdornedElementPlaceholder x:Name="_adornedElementPlaceholder" />
        </Border>
        <ItemsControl
            Grid.Row="1"
            ItemsSource="{Binding}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBox
                        Style="{StaticResource ErrorMessageStyle}"
                        Text="{Binding Path=ErrorContent, Mode=OneWay}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</ControlTemplate>
 

Я попытался изменить все привязки для поиска NotifyDataErrorInfo, но безуспешно.
Какие изменения мне нужно внести в шаблон, чтобы получить доступ к ошибкам проверки в свойстве NotifyDataErrorInfo MyViewModel?

РЕДАКТИРОВАТЬ: похоже, что в композиционном подходе ErrorsChanged всегда имеет значение null, и представление никогда не уведомляется. Я предполагаю, что когда сама модель представления реализует INotifyDataErrorInfo, платформа назначает делегата с помощью ErrorsChangedEventManager. Но теперь я оставляю это вне цикла. Таким образом, похоже, что композиция не будет работать для этого подхода. Правильна ли эта оценка?

Ответ №1:

Свойство называется ‘NotifyDataErrorInfo’, вам необходимо привязать ItemsSource к этому свойству

 <ItemsControl
            Grid.Row="1"
            ItemsSource="{Binding NotifyDataErrorInfo}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <TextBox
                        Style="{StaticResource ErrorMessageStyle}"
                        Text="{Binding Path=ErrorContent, Mode=OneWay}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
 </ItemsControl>
 

Если controltemplate не извлекает datacontext, его необходимо добавить

 <ControlTemplate DataContext={Binding DataContext, 
RelativeSource={RelativeSource AncestorType={x:Type views:YourView}}} x:Key="TextBoxValidationErrorTemplate">
 

Комментарии:

1. Спасибо за ваше предложение. Я попробовал это, но затем понял, что ErrorsChanged никогда не устанавливается. Смотрите мое последнее редактирование. Дайте мне знать, если у вас есть еще какие-либо идеи. Спасибо!