#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 никогда не устанавливается. Смотрите мое последнее редактирование. Дайте мне знать, если у вас есть еще какие-либо идеи. Спасибо!