【问题标题】:WPF MVVM Validation Using IDataErrorInfo使用 IDataErrorInfo 进行 WPF MVVM 验证
【发布时间】:2014-07-08 18:28:25
【问题描述】:

我创建了一个需要验证的 Person MVVM 模型。我正在使用 IDataErrorInfo 类并验证用户。但是当屏幕加载时,文本框已经是红色/已验证,表明该字段需要填写。我相信这是因为我在 InitializeComponent 中绑定了 PersonViewModel。我尝试将 LostFocus 用于更新触发器,但没有做任何事情。

这是我的 PersonViewModel:

 public class PersonViewModel : IDataErrorInfo
    {
        private string _firstName;
        private string _lastName; 

        public string LastName { get; set; }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }



        public string this[string columnName]
        {
            get
            {
                string validationResult = String.Empty; 

                switch(columnName)
                {
                    case "FirstName":
                        validationResult = ValidateFirstName();
                        break; 

                    case "LastName":
                        validationResult = ValidateLastName();
                        break; 

                    default:
                        throw new ApplicationException("Unknown property being validated on the Product");
                }

                return validationResult; 
            }
        }

        private string ValidateLastName()
        {
            return String.IsNullOrEmpty(LastName) ? "Last Name cannot be empty" : String.Empty;
        }

        private string ValidateFirstName()
        {
            return String.IsNullOrEmpty(FirstName) ? "First Name cannot be empty" : String.Empty;
        }



    }

这里是 XAML:

  <StackPanel>
        <TextBlock>First Name</TextBlock>
        <TextBox Text="{Binding FirstName, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" Background="Gray"></TextBox>
        <TextBlock>Last Name</TextBlock>
        <TextBox Text="{Binding LastName, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" Background="Gray"></TextBox>
    </StackPanel>

MainWindow.cs:

  public MainWindow()
        {
            InitializeComponent();


            _personViewModel = new PersonViewModel();

            this.DataContext = _personViewModel; 



        }

我错过了什么吗?我不希望在屏幕加载时触发验证。我只希望在用户失去文本框的焦点时触发它。

【问题讨论】:

  • 你试过把UpdateSourceTrigger改成LostFocus
  • 是的,我将其更新为 LostFocus,但没有任何作用。
  • 您的“错误”属性 getter 抛出异常——这可能是个问题?
  • @McGarnagle:WPF 不使用错误,我相信它是 WinForms 遗留下来的。
  • @johndoe 为什么您不希望用户最初看到表单上的要求?

标签: c# wpf


【解决方案1】:

与其对抗 WPF 默认工作方式的潮流,不如考虑重新定义 UI,使错误显示“适合”屏幕加载和数据输入错误的场景。此外,用户应该对所需内容的空白表格有一些提示。

【讨论】:

  • 保持原样对于“必需”类型验证绝对没问题。但是,一旦验证结果变得更加昂贵(例如,您需要接触数据库或类似的东西),请考虑缓存验证结果
【解决方案2】:

创建一个方法来进行验证,并将验证结果存储在字典中:

private Dictionary<string, string> _validationErrors = new Dictionary<string, string>();

public void Validate(string propertyName)
{
    string validationResult = null;
    switch(propertyName)
    {
        case "FirstName":
            validationResult = ValidateFirstName();
            break; 
        }
        //etc.
    }

    //Clear dictionary properly here instead (You must also handle when a value becomes valid again)
    _validationResults[propertyName] = validationResult;
    //Note that in order for WPF to catch this update, you may need to raise the PropertyChanged event if you aren't doing so in the constructor (AFTER validating)
}

然后将您的 ViewModel 更新为:

  1. 让索引器改为从 _validationErrors 返回结果(如果存在)。
  2. 在您的设置器中调用 Validate()。
  3. 可选地,在 Validate() 中,如果 propertyName 为 null,则验证所有属性。

WPF 会调用 indexer 来显示错误,既然你在返回一些东西,它就会认为有错误。除非您使用此解决方案明确调用 Validate(),否则不会。

编辑:另请注意,现在在 .NET 4.5 中有一种更有效的方法来实现验证,称为 INotifyDataErrorInfo

【讨论】:

  • 是的,我可以为此创建一个 ValidationEngine 框架,但我确实需要在 WPF 中使用 DataBinding 找到一个不错的解决方案。
  • 这个正在使用DataBinding。 WPF 将绑定到您的索引器,并看到它返回一个非空、非空字符串。这是 WPF 必须确定属性是否有效的唯一方法。此外,调用本地存储的字典(无论如何这对性能来说都是一个好主意)框架有点过头了。
猜你喜欢
  • 2014-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
相关资源
最近更新 更多