首页 > 解决方案 > 使用组合从 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。当我探索通过组合实现相同结果时,情况已不再如此。)

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,但没有运气。我需要对模板进行哪些更改才能访问 MyViewModel 的 NotifyDataErrorInfo 属性上的验证错误?

编辑: 似乎在组合方法中,ErrorsChanged 始终为空,并且永远不会通知视图。我猜当视图模型本身实现 INotifyDataErrorInfo 时,框架使用 ErrorsChangedEventManager 分配委托。但现在我把它排除在外了。因此,组合似乎不适用于这种方法。这个评价正确吗?

标签: wpfvalidationxamlbindinginotifydataerrorinfo

解决方案


该属性称为“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={Binding DataContext, 
RelativeSource={RelativeSource AncestorType={x:Type views:YourView}}} x:Key="TextBoxValidationErrorTemplate">

推荐阅读