代码之家  ›  专栏  ›  技术社区  ›  Brian Sullivan

如何使WPF在初始显示控件时不显示验证错误?

  •  12
  • Brian Sullivan  · 技术社区  · 15 年前

    当我第一次向用户显示我的屏幕时,我宁愿在用户有机会填写任何表单字段之前,不让所有必需字段的验证消息都显示出来。我已经设置了 UpdateSourceTrigger 在我绑定到 LostFocus ,但第一次显示控件时仍显示错误。有没有办法避开这个?

    XAML:

    <TextBox Text="{Binding Path=OpeningOdometer, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" />
    

    视图模型:

    [Required(ErrorMessage = "Please enter the opening odometer.")]
    [Range(0, Double.MaxValue, ErrorMessage = "Opening Odometer must be a positive number")]        
    public string OpeningOdometer
    {
        get { return _openingOdometer; }
        set
        {
            _openingOdometer = value;
            NotifyOfPropertyChange(() => OpeningOdometer);
        }
    }
    
    // Implementation of IDataErrorInfo
    public string this[string columnName]
    {
        get
        {
            // This uses the System.ComponentModel.DataAnnotations placed on
            // the OpeningOdometer property to produce an error string
            // if the value of the property is in violation of any of the 
            // annotated rules.
            return _valHelper.GetErrorsForProperty(columnName, this);
        }
    }
    
    3 回复  |  直到 12 年前
        1
  •  8
  •   Robert Rossney    15 年前

    我不把验证逻辑放在索引器中。这会将对验证时间的控制权转到视图上。在方案中,只要视图请求属性的错误信息,它就会触发验证。我不知道会发生这种情况的每一种情况,我打赌你也不知道。

    相反,我将属性的验证逻辑(更准确地说,是对验证函数的调用)放在其setter中。我将错误消息存储在键入属性名称的字典中,并让索引器查找该属性的错误消息。

    那么,默认情况下,错误消息是最新的,具有该属性的当前值。每当视图更新一个属性并请求它的新错误信息时,它就会得到正确的答案。

    但是你也可以很好地控制字典中的内容。如果希望某个属性在UI中显示为有效,只需清除字典中的错误消息(并引发 PropertyChanged ,这样用户界面将知道获取新的错误消息)。或者,在构造视图模型对象时,可以设置属性的支持字段而不是属性本身,从而绕过验证。

        2
  •  2
  •   wpfwannabe    15 年前

    如果您努力发布相关代码/xaml的片段,您可以得到更好的答案。这将使复制和消除许多猜测变得更容易。

    尝试设置 ValidatesOnTargetUpdated="False" 验证规则,看看是否有帮助。

        3
  •  2
  •   GONeale    12 年前

    只是为了说明我如何利用 IDataErrorInfo

    我调用了一个名为 OnDataUpdated() 在我的视图绑定属性的每个setter中,例如:

        private string username;
        public string Username
        {
            get { return username; }
            set
            {
                username = value;
                OnDataUpdated();
            }
        }
    
        private string password;
        public string Password
        {
            get { return password; }
            set
            {
                password = value;
                OnDataUpdated();
            }
        }
    

    然后在里面 OnDataUpdated()。 将私有字段布尔值标记为 true 指示数据首次更改( FormType 仅对我的业务案例是必要的):

    private void OnDataUpdated()
    {
       dataChanged = true;
       // .. Any other universal RaisePropertyChanged() events you may want to call to get your UI into sync. Eg. RaisePropertyChanged(() => CanConfirm);
    }
    

    然后在我的 爱达塔错误信息 索引器属性我执行以下操作(我将其拆分,以便也可以手动调用“validForm()”来执行表单验证。

    public string this[string columnName]
            {
                get
                {
                    string result = null;
                    if (columnName == "Username")
                    {
                        // If other payment amounts have fully paid for balance, and cash amount has been entered, deny
                        if (!ValidForm(FormType.Step1, columnName))
                            result = "Please enter the username field.";
                    }
                    else if (columnName == "Password")
                    {
                        if (!ValidForm(FormType.Step1, columnName))
                            result = "Please enter the password field.";
                    }
                    return result;
                }
            }
    
            /// <summary>
            /// Test if valid form.
            /// </summary>
            /// <param name="formType">Specify which form we should validate.</param>
            /// <param name="columnName">If ommitted, entire form will be validated.</param>
            /// <returns></returns>
            private bool ValidForm(FormType formType, string columnName = null)
            {
                // This field is used to denote when data has changed on the form.
                // If data has changed, we know we can activate any form validation.
                // We do not activate the form validation until after a user has typed
                // something in at least.
                if (!dataChanged) return true;
    
                var errors = false;
                if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Username") && string.IsNullOrEmpty(Username)))
                    errors = true;
                if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Password") && string.IsNullOrEmpty(Password)))
                    errors = true;
                return !errors;
            }
    

    效果很好。现在我只有验证样式出现在用户编辑表单之后。

    如果你想在蛋糕上加点糖霜,你可以在我的评论中 RaisePropertyChanged(() => CanConfirm); OnDataUpdated()。 方法并将其绑定到确认按钮 IsEnabled={Binding CanConfirm} 具有关联属性:

    /// <summary>
    /// Can the user confirm step 1?
    /// </summary>
    public bool CanConfirm
    {
        get { return ValidForm(FormType.Step1); }
    }
    

    只有当您的表单也有效时,您的按钮才会启用。:)

    享受吧!祝巨兽WPF好运。