INotifyDataErrorInfo.GetErrors在何时使用null和String.empty?

12
InotifyDataErrorInfo.GetErrors 的 MSDN 页面 中提到,GetErrors 方法被调用时需要传入一个参数,该参数可以是以下三者之一:
  • 要检索错误信息的属性名称
  • Null
  • String.Empty
文档没有说明什么情况下会使用 null 和 String.Empty 两个值进行方法调用。我在我的应用程序中看到了这两种情况,我需要了解在何时可以期望使用其中之一。
澄清:我不是在问如何实现 GetErrors 方法(我只是测试了 null 和 empty 两种情况)。问题更多地是为了理解为什么 WPF 框架有时会使用 null,有时会使用空字符串来调用此方法(我在我的应用程序中遇到了这两种情况)。如果意图是询问未绑定到特定属性的错误,请为什么需要使用两种不同的调用值,而只使用其中一种就足够了?

我理解你的问题是为什么要区分 nullstring.Empty - DHN
4个回答

2

当调用程序想要知道实体所有参数的错误,而不是特定参数的错误时,您必须预期nullstring.Empty。因此,您不应区分nullstring.Empty

所以应该这样处理:

if(string.IsNullOrEmpty(propertyName))
{
    // return all errors
}
else
{
    // return the error for the parameter 'propertyName'
}

简而言之,答案是:你不应该关心。 - Roland Bär
当使用null和string.Empty调用时,我不会搜索模式,因为接口描述允许两者。因此,我相信一些微软开发人员使用了null,而其他人则使用了string.Empty。因此,您将找到实现调用类的组。但这并不能帮助您编写应用程序或类似的东西。 - Roland Bär
1
我不同意这种行为。如果有一些在MSDN文档中没有记录的原因,我想了解并理解这两种情况之间的区别。如果没有区别,那么框架就存在问题。 - disklosr
你应该针对接口进行实现,而不是其背后的具体实现。由于请求所有错误时允许使用'null'和'string.Empty',因此两种变体都将被使用。我不明白为什么框架会有问题。也许接口设计得不太好。最好使用两个函数,并禁止将'null'和'string.Empty'作为此函数的值。 - Roland Bär
我被这个错误困扰了相当长的时间,直到我找到了这个解决方案。我已经实现了INotifyDataErrorInfo.GetErrors,但完全没有考虑过对string.IsNullOrEmpty(propertyName)进行评估,而GetErrors一直抛出ArgumentException,因为用于存储错误的字典中propertyName的键是""或null。 - crakama

2

WPF会调用InotifyDataErrorInfo.GetErrors(null/string.Empty)方法来获取“整个视图模型”的错误。所有具有数据上下文或绑定到具有“整个视图模型错误”的视图模型的控件都将使用错误模板呈现。例如,您有一个名为Credentials的视图模型,其中包含两个属性:UserName和Password。您可以实现如下:

IEnumerable InotifyDataErrorInfo.GetErrors(string propertyName)
    {
        if (UserNames.Length == 0)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                return "Some credentials component is wrong.";
            }
            else if (propertyName == "UserNames")
            {
                return "User name is required field.";
           }
        }
    }

然而,在大多数情况下,当string.IsNullOrEmpty(propertyName)时,您可能会返回null。


2

当绑定引用无属性时,例如默认Path,则会得到空参数:

最初的回答: You get the null argument when the binding refers to no property, as with the default Path:

DataContext="{Binding ValidatesOnNotifyDataErrors=True}"
DataContext="{Binding Path=., ValidatesOnNotifyDataErrors=True}"

这可以通过在路径中指定实际的属性来避免。当然,它可以是视图模型中的属性,包括一个只返回"this"的属性。"Original Answer"翻译成"最初的答案"。
Tag="{Binding Path=DataContext, RelativeSource={RelativeSource Self}, ValidatesOnNotifyDataErrors=True}"

关于string.Empty,在内部BindingExpression.UpdateNotifyDataErrors方法的框架中已经明确说明:

最初的回答

List<object> propertyErrors = GetDataErrors(indei, propertyName);
List<object> valueErrors = GetDataErrors(dataErrorValue, String.Empty);
List<object> errors = MergeErrors(propertyErrors, valueErrors);

警告: 注意上面的聚合操作,因此如果您使用string.IsNullOrEmpty来验证框架是否要求实体级错误,并且无论"null" vs. string.Emtpy都返回相同的错误,您可能会在UI中获得重复的消息(一个为“null”,另一个为string.Empty)。至少在今天的.NET框架版本中是这样。

最初的回答: 警告:请注意上述聚合操作,如果您使用string.IsNullOrEmpty来验证框架是否请求实体级别的错误,并且无论是“null”还是“string.Emtpy”,都返回相同的错误,那么您可能会在UI中看到重复的消息(一个为“null”,另一个为string.Empty)。至少在当前的.NET框架版本中是如此。


0

INotifyDataErrorInfo.GetErrors 什么时候使用 null 或 String.empty 调用?

如果您想验证单个属性,您将调用

RaiseEvent ErrorsChanged(Me, New DataErrorsChangedEventArgs("PropertyName"))

从该属性的setter方法中返回。

如果您想验证整个实体,您将调用

RaiseEvent ErrorsChanged(Me, New DataErrorsChangedEventArgs(String.Empty))

从某个“中心”位置,例如保存按钮点击或窗口关闭。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接