带输入验证的WPF命令绑定-如何启用;“保存”;仅当所有输入均有效时,才单击此按钮
在我的ViewModel中,我实现了IDataErrorInfo接口(以及INotifyPropertyChanged)。输入验证按预期工作,我在那里没有问题 我将此属性作为IDataErrorInfo的一部分带输入验证的WPF命令绑定-如何启用;“保存”;仅当所有输入均有效时,才单击此按钮,wpf,mvvm,icommand,idataerrorinfo,relaycommand,Wpf,Mvvm,Icommand,Idataerrorinfo,Relaycommand,在我的ViewModel中,我实现了IDataErrorInfo接口(以及INotifyPropertyChanged)。输入验证按预期工作,我在那里没有问题 我将此属性作为IDataErrorInfo的一部分公共字符串错误{get{return this[null];}}据我所知,错误应该是空的,如果所有经过验证的输入都通过了验证,那么我将其作为CanExecute方法传递 return !string.IsNullOrEmpty(Error); 但是,我的“保存”按钮从未启用。我的问题是,
公共字符串错误{get{return this[null];}}
据我所知,错误
应该是空的,如果所有经过验证的输入都通过了验证,那么我将其作为CanExecute方法传递
return !string.IsNullOrEmpty(Error);
但是,我的“保存”按钮从未启用。我的问题是,canexecutechange
从不触发。如果这是真的,我应该在哪里以及如何触发它
这是我的休闲班。我尝试过其他的实施方式,但结果都是一样的。我认为它是有效的,因为如果我不将CanExecute方法传递给构造函数,“save”按钮是启用的
public class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter) { execute(); }
}
在ViewModel构造函数中:
InsertCommand = new RelayCommand(ExecuteInsert, CanExecuteInsert);
CanExecute:
bool CanExecuteInsert()
{
return !string.IsNullOrEmpty(Error);
}
您没有添加足够的代码,我们无法准确地告诉您问题所在。但是,您正在采取正确的方法。我还使用了
IDataErrorInfo
接口,但我在实现它的基类中添加了一些额外的属性:
public string Error // actual IDataErrorInfo Member
{
get
{
if (!HasError) return string.Empty;
StringBuilder errors = new StringBuilder();
foreach (string error in Errors) errors.AppendUniqueOnNewLineIfNotEmpty(error);
return errors.ToString();
}
}
public virtual ObservableCollection<string> Errors
{
get { return errors; }
}
public virtual bool HasError
{
get { return Errors != null && Errors.Count > 0; }
}
因此,为了回答您的实际问题,我将如下处理Save命令的CanExecute
功能:
public override ICommand Save
{
get { return new ActionCommand(action => SaveCommand(), canExecute =>
CanSave(DigitalServiceProviderPriceTier)); }
}
...
private bool CanSave(DigitalServiceProviderPriceTier digitalServiceProviderPriceTier)
{
return digitalServiceProviderPriceTier != null &&
digitalServiceProviderPriceTier.HasChanges &&
!digitalServiceProviderPriceTier.HasError; // <-- Important part
}
您正在使用null
值调用索引器,因此索引器中的代码返回的实际上是错误
属性值。如果没有验证错误,索引器还应返回空字符串:
public override string this[string propertyName]
{
get
{
string error = string.Empty;
if (propertyName == "SomePropertyName" && SomePropertyName.IsNullOrEmpty())
error = "You must enter some property.";
if (propertyName == "OtherPropertyName" && OtherPropertyName.Length != 3)
error = "The OtherPropertyName must be 3 characters long.";
...
return error;
}
}
然后在Error
属性中,您应该调用要验证的实际属性名,就像我在Errors
属性中所做的那样,而不是null
。因此,在上面的示例中,您可以在Error
属性中调用如下内容:
string error = this["SomePropertyName"];
if (error == string.Empty) error = this["OtherPropertyName"];
return error;
再一次,我写了太多的信息。。。我只是希望这一切对你有意义,你不会带着几十个新问题回来。希望这已经足够清楚了。您还没有为我们添加足够的代码来准确地告诉您问题所在。但是,您正在采取正确的方法。我还使用了IDataErrorInfo
接口,但我在实现它的基类中添加了一些额外的属性:
public string Error // actual IDataErrorInfo Member
{
get
{
if (!HasError) return string.Empty;
StringBuilder errors = new StringBuilder();
foreach (string error in Errors) errors.AppendUniqueOnNewLineIfNotEmpty(error);
return errors.ToString();
}
}
public virtual ObservableCollection<string> Errors
{
get { return errors; }
}
public virtual bool HasError
{
get { return Errors != null && Errors.Count > 0; }
}
因此,为了回答您的实际问题,我将如下处理Save命令的CanExecute
功能:
public override ICommand Save
{
get { return new ActionCommand(action => SaveCommand(), canExecute =>
CanSave(DigitalServiceProviderPriceTier)); }
}
...
private bool CanSave(DigitalServiceProviderPriceTier digitalServiceProviderPriceTier)
{
return digitalServiceProviderPriceTier != null &&
digitalServiceProviderPriceTier.HasChanges &&
!digitalServiceProviderPriceTier.HasError; // <-- Important part
}
您正在使用null
值调用索引器,因此索引器中的代码返回的实际上是错误
属性值。如果没有验证错误,索引器还应返回空字符串:
public override string this[string propertyName]
{
get
{
string error = string.Empty;
if (propertyName == "SomePropertyName" && SomePropertyName.IsNullOrEmpty())
error = "You must enter some property.";
if (propertyName == "OtherPropertyName" && OtherPropertyName.Length != 3)
error = "The OtherPropertyName must be 3 characters long.";
...
return error;
}
}
然后在Error
属性中,您应该调用要验证的实际属性名,就像我在Errors
属性中所做的那样,而不是null
。因此,在上面的示例中,您可以在Error
属性中调用如下内容:
string error = this["SomePropertyName"];
if (error == string.Empty) error = this["OtherPropertyName"];
return error;
再一次,我写了太多的信息。。。我只是希望这一切对你有意义,你不会带着几十个新问题回来。希望它足够清晰。显示InsertCommand是如何初始化的及其CanExecute@lll在末尾添加了它。显示InsertCommand它是如何初始化的及其CanExecute@lll我最近刚开始使用WPF,在IDataErrorInfo的所有示例中,Error属性都是这样实现的。它用于验证,所以我不认为这是个问题。回家后我会试试你的建议。它奏效了,谢谢!我在这里也有一个逻辑缺陷return!string.IsNullOrEmpty(错误)代码>当然应该没有否定。我最近刚开始使用WPF,在IDataErrorInfo的所有示例中,Error属性都是这样实现的。它用于验证,所以我不认为这是个问题。回家后我会试试你的建议。它奏效了,谢谢!我在这里也有一个逻辑缺陷return!string.IsNullOrEmpty(错误)当然,代码>应该没有否定。