wpf mvvm错误验证 [英] wpf mvvm error validation

查看:168
本文介绍了wpf mvvm错误验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的wpf应用程序,如果表单有错误,我试图停用保存按钮。

I have a simple wpf application and I am trying to deactivate the save button if the form has errors.

问题是,虽然验证看起来工作完美,我不知道为什么,但是我正在从负责检查错误的方法中得到所有的时间。

The Problem is that, although the validation it looks to works perfect, I don't know why but I am getting all the time false from the method which is responsible to check the errors.

让我更清楚提供代码。

这是MainWindow.Xaml.cs中的代码

This is the code from MainWindow.Xaml.cs

private readonly HashSet<ValidationError> errors = new HashSet<ValidationError>();
    private Lazy<MainWindowViewModel> viewModel;

    public MainWindow() {
        InitializeComponent();
        InitializeValidaton();
    }

    void InitializeValidaton() {
        viewModel = new Lazy<MainWindowViewModel>();
        Validation.AddErrorHandler(this, ErrorChangedHandler);
    }

    private void ErrorChangedHandler(object sender, ValidationErrorEventArgs e) {
        if (e.Action == ValidationErrorEventAction.Added) {
            errors.Add(e.Error);
        } else {
            errors.Remove(e.Error);
        }
        //I set a breakpoint here and it returns the correct value. False if it has errors  and True if not
        viewModel.Value.IsValid = !errors.Any();

    }

这是按钮的命令

 public ICommand SaveItem {
        get { return new RelayCommand(SaveItemExecute,CanSaveItem); }
    }
 private bool CanSaveItem() {
        return IsValid;
    }

  //I set up here a breakpoint and it returns the correct value just once.
  //The application looked up on CanSaveItem all the time and except the first time, it returns wrong value
  private bool _isValid;
    public bool IsValid {
        get { return _isValid; }
        set {
            _isValid = value;
            RaisePropertyChanged("IsValid");
  }
    }

验证规则 p>

Validation Rules

[Required(ErrorMessage = "Please enter Title")]
    [StringLength(100, ErrorMessage = "The maximum length is 100")]
    string Name { get; set; }

我不知道是否有意义,但按钮我想要停用在UserControl中。

I don't know if it makes any sense, but the button I want to deactivate is in a UserControl.

我不明白为什么canExecute方法在userControl中,触发了不止一次。有什么方法,如果我用,它有同样的反应。我提到userControl,因为如果我在mainWindow中使用相同的方法(在ICommand的一部分),它只会触发一次

我会欣赏如果有人可以帮助我这个。

I will appreciate if could anyone help me with this.

谢谢

推荐答案

而是使用您的模型发布验证的工作示例。根据需要调整此示例,并且可能会发现产生不正确工作的差异。

I would rather post a working example of validation using your model. Adjust this example as you need, and probably you will find difference that produce an incorrect work.

MainWindow.xaml

<StackPanel>
    <TextBox x:Name="ValidatedTextBox" Width="200">
        <TextBox.Text>
            <Binding Path="EnteredText" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:NotEmptyInputRule ValidatesOnTargetUpdated="True" />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <Button Content="Save" Width="60" IsEnabled="{Binding IsValid}" />
</StackPanel>

属性 EnteredText 必须存在于ViewModel中:

Property EnteredText must exist in the ViewModel:

class MainWindowViewModel : INotifyPropertyChanged
{
    public ICommand SaveItem
    {
        get { return new SimpleCommand(SaveItemExecute, CanSaveItem); }
    }

    public void SaveItemExecute()
    {
        //save
    }

    private bool CanSaveItem()
    {
        return IsValid;
    }

    //I set up here a breakpoint and it returns the correct value just once.
    //The application looked up on CanSaveItem all the time and except the first time, it returns wrong value
    private bool _isValid;
    public bool IsValid
    {
        get { return _isValid; }
        set
        {
            _isValid = value;
            OnPropertyChanged("IsValid");
        }
    }

    public string EnteredText { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

不要在MainWindow中设置 DataContext

And don't forget to set DataContext in the MainWindow.

    public MainWindow()
    {
        InitializeComponent();
        InitializeValidaton();
        this.DataContext = viewModel.Value;
    }

还有Command类和验证规则。

There are also the Command class and the validation rule.

public class SimpleCommand : ICommand
{
    /// <summary>
    /// Gets or sets the Predicate to execute when the CanExecute of the command gets called
    /// </summary>
    public Predicate<object> CanExecuteDelegate { get; set; }

    /// <summary>
    /// Gets or sets the action to be called when the Execute method of the command gets called
    /// </summary>
    public Action<object> ExecuteDelegate { get; set; }

    public SimpleCommand(Action execute, Func<bool> canExecute)
    {
        this.ExecuteDelegate = _ => execute();
        this.CanExecuteDelegate = _ => canExecute();
    }

    #region ICommand Members

    /// <summary>
    /// Checks if the command Execute method can run
    /// </summary>
    /// <param name="parameter">THe command parameter to be passed</param>
    /// <returns>Returns true if the command can execute. By default true is returned so that if the user of SimpleCommand does not specify a CanExecuteCommand delegate the command still executes.</returns>
    public bool CanExecute(object parameter)
    {
        if (CanExecuteDelegate != null)
            return CanExecuteDelegate(parameter);
        return true;// if there is no can execute default to true
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Executes the actual command
    /// </summary>
    /// <param name="parameter">THe command parameter to be passed</param>
    public void Execute(object parameter)
    {
        if (ExecuteDelegate != null)
            ExecuteDelegate(parameter);
    }

    #endregion

}

class NotEmptyInputRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (value != null)
        {
            string input = value as string;

            if (input.Length > 0)
                return new ValidationResult(true, null);
        }

        return new ValidationResult(false, "Validation error. Field input required.");
    }
}

这篇关于wpf mvvm错误验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆