使用Wpf Mvvm IDataErrorInfo在不同窗口中使用dataAnnotation正则表达式验证属性

时间:2018-07-17 04:29:00

标签: c# wpf mvvm

请提供更详细的解决方案!我使用的代码几乎与Karel所示的代码相同: Using dataAnnonation regular expression validation attribute in Wpf Mvvm IdataErrorInfo

它就像一个魅力! 我有一个要在其中使用Attributes和IDataErrorInfo进行验证的模型,该模型可以完美地工作。

  simplified Model: 

  public class SiESTAModel : BaseModel
  {
         [Required]
          public string MyTestsceanrioNameTemp { get; set; }
  }

在我的BaseModel类中,我有运行以下代码:

public class BaseModel : INotifyPropertyChanged, IDataErrorInfo
{
        private static List<PropertyInfo> _propertyInfos;
        public Dictionary<string, string> Errors { get; set; } = new Dictionary<string, string>();


            public string this[string columnName]
            {
                get
                {
                    CollectErrors();
                    return Errors.ContainsKey(columnName) ? Errors[columnName] : string.Empty;
                }
            }


     private void CollectErrors()
            {
                Errors.Clear();
                PropertyInfos.ForEach(
                    prop =>
                    {
                        //Validate generically
                        var errors = new List<string>();
                        var isValid = TryValidateProperty(prop, errors);
                        if (!isValid)

                            Errors.Add(prop.Name, errors.First());
                    });
                // we have to this because the Dictionary does not implement INotifyPropertyChanged            
                OnPropertyChanged(nameof(HasErrors));
                OnPropertyChanged(nameof(IsOk));
                // commands do not recognize property changes automatically
                OnErrorsCollected();
            }


        private List<PropertyInfo> PropertyInfos
        {
            get
            {
                return _propertyInfos
                       ?? (_propertyInfos =
                           GetType()
                               .GetProperties(BindingFlags.Public | BindingFlags.Instance)////////////////////////////////////////////
                                .Where(prop => prop.IsDefined(typeof(ValidationAttribute), true))
                               .ToList());
            }
        }



        private bool TryValidateProperty(PropertyInfo propertyInfo, List<string> propertyErrors)
        {
            var results = new List<ValidationResult>();
            var context = new ValidationContext(this) { MemberName = propertyInfo.Name };

                var propertyValue = propertyInfo?.GetValue(this);

                    // Validate the property
                    var isValid = Validator.TryValidateProperty(propertyValue, context, results);

                    if (results.Any())
                    {
                        propertyErrors.AddRange(results.Select(c => c.ErrorMessage));
                    }
                    return isValid;


            }
}

此模型是在我的ViewModel中创建的:

public class DataErrorInfoViewModel : BaseViewModel
{
   public SiESTAModel SiESTA { get; set; } 

    public DataErrorInfoViewModel()
    {
        // create SiESTA
        SiESTA = new SiESTAModel();
    }
 }

在MainView中,我有一些文本框用于实现登录并检查输入值。此登录是作为用户控件在视图中实现的,非常适合MainView中的所有属性。
例如:

TextBox  Text="{Binding CurrentUser.SiestaIp, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=True}" MinWidth="180"  Width="AUTO" Margin="10,0,10,0"

但是现在我想通过新窗口添加一些新设备,并且我还要在此窗口中检查输入值。我已经用MVVM light和Messenger来实现了。

ViewModel:

public RelayCommand OpenAddWindowCommand { get; private set; }

        OpenAddWindowCommand= new RelayCommand(() =>
        {


            MessengerInstance.Send(new OpenAddWindowMessage());
        }); 

消息:

public class OpenAddWindowMessage
{
    public OpenAddWindowMessage()
    {

    }

}

在我的视图项目中,我实现了这样的消息侦听器类,该类通过绑定来调用。

    public class MessageListener
    {


        public AddWindow TempAddWindow;

        public MessageListener()
        {
            InitMessenger();
        }
 private void InitMessenger()
        {
            Messenger.Default.Register<OpenAddWindowMessage>(this, msg =>
                {
                    TempAddWindow = new AddWindow();

                    TempAddWindow.ShowDialog();



                }

            );
         }
     }

在这个AddWindow视图中,我有一些文本框,应该检查这些文本框是否需要在文章开头看到。数据上下文也是我的MainViewModel,就像在MainView中一样。

        <TextBox  FontSize="16"  Text="{Binding SiESTA.MyTestsceanrioNameTemp, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=true}"  Grid.Column="1" Grid.Row="0"></TextBox>

现在是问题所在!如果仅打开MainView窗口,则IdataErrorInfo可以完美工作。但是,当第二个窗口打开并获得焦点时,我的媒体资源的获取值就会从基本模型中崩溃。

崩溃行:

var propertyValue = propertyInfo.GetValue(this);

例外:

  

System.Reflection.TargetException->对象与目标类型不匹配。

这是因为反射不仅从新打开的AddWindow收集值,而且还从mainview窗口收集我的Loginvalues,我只想检查MainWindow是否打开。而且,主视图属性中的getvalue崩溃。

protected List<PropertyInfo> PropertyInfos
{
    get
    {
        return _propertyInfos
               ?? (_propertyInfos =
                   GetType()
                       .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                       .Where(prop => prop.IsDefined(typeof(ValidationAttribute), true))
                       .ToList());
    }
}

那么,该怎么做才能使反射仅从实际的优化窗口中收集值?还是可以解决其他问题?谢谢!我希望这可以解释清楚:)

0 个答案:

没有答案