【问题标题】:Accessing INotifyDataErrorInfo validation errors from XAML error template using composition使用组合从 XAML 错误模板访问 INotifyDataErrorInfo 验证错误
【发布时间】:2021-02-01 21:33:16
【问题描述】:

我的视图模型基类最初是实现 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 分配委托。但现在我把它排除在外了。 因此,组合似乎不适用于这种方法。这个评估是否正确?

【问题讨论】:

    标签: wpf validation xaml binding inotifydataerrorinfo


    【解决方案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={Binding DataContext, 
    RelativeSource={RelativeSource AncestorType={x:Type views:YourView}}} x:Key="TextBoxValidationErrorTemplate">
    

    【讨论】:

    • 感谢您的建议。我试过了,但后来意识到 ErrorsChanged 永远不会被设置。查看我的最新编辑。如果您有更多想法,请告诉我。谢谢!
    猜你喜欢
    • 2021-08-13
    • 2016-12-03
    • 2018-06-03
    • 2016-07-11
    • 1970-01-01
    • 2017-04-30
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多