【问题标题】:When is INotifyDataErrorInfo.GetErrors called with null vs String.empty?什么时候用 null vs String.empty 调用 INotifyDataErrorInfo.GetErrors?
【发布时间】:2016-05-01 19:13:59
【问题描述】:

msdn page for InotifyDataErrorInfo.GetErrors 中,它说 GetErrors 方法是使用参数调用的,该参数可以是:

  • 我们要为其检索错误信息的属性的名称
  • String.Empty

文档没有说明何时使用 null 与 String.Empty 调用此方法。我在我的应用中看到了这两种情况,我需要了解何时可以期待其中一种。

澄清:我不是在问我应该如何实现 GetErrors 方法(我只是测试 null 和 empty)。问题更多的是要理解为什么 WPF 框架 有时会尝试使用 null 有时使用空字符串来调用此方法(我在我的应用程序中遇到了这两种情况)。如果目的是询问与特定属性无关的错误,为什么在调用时使用两个不同的值就足够了?

【问题讨论】:

  • 我是否理解您的问题,您要问的是,为什么要区分nullstring.Empty

标签: c# .net wpf validation


【解决方案1】:

当调用者想知道的不是特定参数的错误而是实体的所有参数的错误时,您必须同时期待nullstring.Empty。所以你不应该区分nullstring.Empty

那么就这样吧:

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

【讨论】:

  • 简而言之:你不应该关心。
  • 当使用 null 调用模式和使用 string.Empty 调用模式时,我不会搜索模式,因为接口描述允许两者。所以我相信一些微软开发人员使用 null 而其他人使用 string.Empty。所以你会发现哪个组实现了调用类。但这不会帮助您编写应用程序或类似的东西。
  • 我不同意。如果此行为背后的原因未在 msdn 中记录,我想了解它并了解这两种情况之间的区别。如果没有区别,那么框架有问题
  • 你应该针对接口实现,而不是它背后的实现。由于 'null' 和 'string.Empty' 都允许询问所有错误,因此将使用这两种变体。我不明白为什么框架应该有问题。可能接口设计得不是很好。使用两个函数并禁止“null”和“string.Empty”作为该函数的值可能会更好。
  • 我被这个错误困扰了很长一段时间,直到我遇到解决问题的答案。我已经实现了 INotifyDataErrorInfo.GetErrors 但完全没有考虑评估 string.IsNullOrEmpty(propertyName) 和 GetErrors 继续抛出 ArgumentException 用于存储错误的字典中 propertyName 的键是“”或 null。
【解决方案2】:

WPF 调用 InotifyDataErrorInfo.GetErrors(null/string.Empty) 来获取“整个视图模型”的错误。所有具有数据上下文或绑定到具有“整个视图模型错误”的视图模型的控件都将使用错误模板呈现。例如,您有具有两个属性的视图模型凭据:用户名、密码。 你可以实现这样的东西:

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。

【讨论】:

    【解决方案3】:

    当绑定没有引用任何属性时,您将获得 null 参数,与默认路径一样:

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

    这可以通过在路径中指定一个实际属性来避免。当然,它可以是视图模型中的一个属性,包括一个只返回“this”的属性。

    Tag="{Binding Path=DataContext, RelativeSource={RelativeSource Self}, ValidatesOnNotifyDataErrors=True}"
    

    至于string.Emtpy,那是在框架内部明确的BindingExpression.UpdateNotifyDataErrors method

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

    警告:注意上面的聚合操作,所以如果你使用 string.IsNullOrEmpty 来验证框架是否要求实体级错误并返回相同的错误,无论“null”还是字符串.Emtpy,您最终可能会在 UI 中看到重复的消息(一个用于“null”,另一个用于 string.Empty)。至少在今天的 .NET 框架版本中。

    【讨论】:

      【解决方案4】:

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

      如果你想验证单个属性,你会调用

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

      来自该属性的设置器。

      如果你想验证整个实体,你会调用

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-27
        • 1970-01-01
        • 1970-01-01
        • 2019-12-25
        • 2016-09-09
        • 2015-05-14
        • 2018-10-28
        • 2021-02-01
        相关资源
        最近更新 更多