c# - 使用 IDataErrorInfo 验证整个对象

标签 c# wpf idataerrorinfo

我在类中实现了 IDataErrorInfo 接口(interface)来验证对象。但我现在想做的是以编程方式验证整个对象以了解它是否有效。 我一直在谷歌搜索但找不到任何东西。我以为我可以做一些类似 object.Validate() 的事情并知道它是否有效,但是 IDataErrorInfo 没有提供任何类似的方法。

我已经使用 XAML 验证了它,但我还需要在方法中检查它。

有人可以帮助我实现这个目标吗?以防万一,这是我的课:

    namespace Plutus.Data.Domain
{
    using Plutus.Data.Domain.NameMappings;
    using Plutus.Data.Domain.Validation;
    using System;
    using System.ComponentModel;

    public class Phone : IDataErrorInfo
    {
        /// <summary>
        /// Código de área.
        /// </summary>
        public string AreaCode { get; set; }

        /// <summary>
        /// Identificador de tipo de teléfono.
        /// </summary>
        public short? PhoneTypeID { get; set; }

        /// <summary>
        /// Número de teléfono.
        /// </summary>
        public long? PhoneNumber { get; set; }

        /// <summary>
        /// Número de interno.
        /// </summary>
        public string ExtensionNumber { get; set; }

        public string Error { get { return null; } }

        public string this[string columnName]
        {
            get
            {
                string result = null;
                if (columnName == "AreaCode")
                {
                    if (string.IsNullOrWhiteSpace(AreaCode))
                        result = ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(columnName));
                }
                if (columnName == "PhoneTypeID")
                {
                    if (!PhoneTypeID.HasValue)
                        result = ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(columnName));
                }
                if (columnName == "PhoneNumber")
                {
                    if (!PhoneNumber.HasValue)
                        result = ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(columnName));
                }

                return result;
            }
        }
    }
}

扩展解决方案:

也许我没有解释得很好,但我需要的是知道一个对象是否有任何验证错误。基于ethicallogics解决方案,我创建了一个名为IsValid的新方法,在其中检查字典上是否有任何错误:

public bool IsValid()
    {
        ValidateProperty("AreaCode");
        ValidateProperty("PhoneNumber");
        ValidateProperty("PhoneTypeID");

        return Errors.Count == 0 ? true : false;
    }

为了实现这一点,我必须更改 ValidateProperty 方法,以免再次在字典中添加错误键(否则您将收到异常)。然后我首先检查错误是否已经在字典中,只有在没有的情况下才添加它:

public void ValidateProperty(string propertyName)
    {
        if (propertyName == "AreaCode" && string.IsNullOrWhiteSpace(AreaCode))
        {
            if (!Errors.ContainsKey(propertyName))
            Errors.Add(propertyName, ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(propertyName)));
        }
        else if (propertyName == "PhoneTypeID" && !PhoneTypeID.HasValue)
        {
            if (!Errors.ContainsKey(propertyName))
            Errors.Add(propertyName, ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(propertyName)));
        }
        else if (propertyName == "PhoneNumber" && !PhoneNumber.HasValue)
        {
            if (!Errors.ContainsKey(propertyName))
            Errors.Add(propertyName, ErrorMessages.ErrorMessage(ErrorMessages.FieldIsRequired, PhoneNameDictionary.GetValue(propertyName)));
        }

        else if (Errors.ContainsKey(propertyName))
            Errors.Remove(propertyName);
    }

最佳答案

首先你的类必须实现 INotifyPropertyChanged

    public class Phone : IDataErrorInfo, INotifyPropertyChanged
{
    string areaCode;
    public string AreaCode
    {
        get
        {
            return areaCode; 
        }
        set
        {
            if (areaCode != value)
            {
                areaCode = value;
                ValidateProperty("AreaCode"); //Validate on PropertyChanged
                Notify("AreaCode");
            }
        }
    }

    short? phoneTypeId;
    public short? PhoneTypeID
    {
        get
        {
            return phoneTypeId;
        }
        set
        {
            if (phoneTypeId != value)
            {
                phoneTypeId = value;
                ValidateProperty("PhoneTypeID");
                Notify("PhoneTypeID");
            }
        }
    }

    long? phoneNumber;
    public long? PhoneNumber
    {
        get
        {
            return phoneNumber;
        }
        set
        {
            if (phoneNumber != value)
            {
                phoneNumber = value;
                ValidateProperty("PhoneNumber");
                Notify("PhoneNumber");
            }
        }
    }

    string extensionNumber;
    public string ExtensionNumber
    {
        get
        {
            return extensionNumber;
        }
        set
        {
            if (extensionNumber != value)
                extensionNumber = value; Notify("ExtensionNumber");
        }
    }

    public string Error { get { return null; } }

    Dictionary<string, string> errors = new Dictionary<string, string>();

    public string this[string columnName]
    {
        get
        {
            if(errors.ContainsKey(columnName)
                return errors[columnName];

            return null;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void Notify(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    //This could be much more generic but for simplicity 
    void ValidateProperty(string propertyName)
    {
        if (propertyName=="AreaCode" && string.IsNullOrWhiteSpace(AreaCode))
                errors.Add(propertyName,"AreaCode is Mandatory");

        else if (propertyName == "PhoneNumber" && !PhoneNumber.HasValue)
                errors.Add(propertyName, "PhoneNumber can not be null");

        else if(propertyName == "PhoneTypeID" && !PhoneTypeID.HasValue)
            errors.Add(propertyName, "PhoneTypeID can not be null");

        else if(errors.ContainsKey(propertyName))
            errors.Remove(propertyName);
    }

    public void ValidatePhoneObject()
    {
        ValidateProperty("AreaCode");
        ValidateProperty("PhoneNumber");
        ValidateProperty("PhoneTypeID");
        //Must fire property changed so that binding validation System calls IDataErrorInfo indexer
        Notify("AreaCode");
        Notify("PhoneNumber");
        Notify("PhoneTypeID");

    }
}

在 xaml 绑定(bind)中 ValidateOnDataErrors 必须为 True

 <TextBox x:Name="PhoneNumber" Text="{Binding PhoneNumber, ValidatesOnDataErrors=True}"/>

这里我返回了简单的字符串而不是您的 ErrorMessage,因为我不知道它是什么,您可以简单地用您的 ErrorMessage 替换字符串。我希望这能给您一个想法。

关于c# - 使用 IDataErrorInfo 验证整个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20435554/

相关文章:

c# - WPF View 谁导致另一个使用 MVVM

wpf - 如何强制ItemsControl验证行更改?

c# - ThreadPool.QueueUserWorkItem 中的最大排队元素

c# - 变量不保存在对象中

c# - 无法将类型为 'System.Web.UI.WebControls.GridView' 的对象转换为类型 'System.Web.UI.WebControls.LinkButton'

c# - MySQL连接器通用SELECT多表查询方法

c# - WPF 组合框所选项目

c# - 组合框绑定(bind)时出现 NullReferenceException

wpf - 如何使用 IDataErrorInfo 实现条件验证

c# - 如何通过 IDataErrorInfo 在按下保存按钮时验证我的实体?