wpf mvvm错误验证 [英] wpf mvvm error validation
问题描述
我有一个简单的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屋!