我可能会稍微复杂一些,所以让它保持简单。如果将整数绑定到文本框,如果在文本框中键入非法字符,它将获得验证异常。如何根据属性是否具有验证异常来禁用按钮。
我使用MVVM方法在WPF中创建应用程序,但没有任何框架。
我的模型类实现了IDataErrorInfo,如果发生错误,则都具有HasError属性和< propertyName,ErrorMessage>。如果HasError属性在我的命令上更改了我的RaiseCanExecuteChanged以重新评估我们现在是否可以保存。
这样可以正常工作,但仅适用于
等显式数据注释 [MaxLength(3,ErrorMessage = "The text can't be longer than 3")]
[CustomRequiredAttribute]
public string CountryCode
{
get { return m_CountryCode; }
set { SetProperty(ref m_CountryCode, value); }
}
public string m_CountryCode;
另一方面,如果我将一个Integer绑定到文本框并输入非法字符(如字母),则OnValidate函数不会触发,因此错误不会添加到我的集合中。
string IDataErrorInfo.this[string propertyName]
{
get
{
var error = OnValidate(propertyName);
return error;
}
}
这是我的CanExecute
protected override bool CanHandleSaveCommand()
{
return !Feeds.Any(e => e.HasErrors) && IsEdited;
}
这样你可以得到完整的图片是OnValidate方法,它可以正常工作
protected virtual string OnValidate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("Invalid property name", propertyName);
}
var error_summary = new StringBuilder();
PropertyInfo property_info = GetType().GetProperty(propertyName);
var value = property_info.GetValue(this);
var validation_errors = new List<ValidationResult>();
var is_valid = Validator.TryValidateProperty(
value,
new ValidationContext(this, null, null)
{
MemberName = propertyName
},
validation_errors);
if (is_valid)
{
if (Errors.ContainsKey(propertyName))
{
Errors.Remove(propertyName);
PropertyChanged(this, new PropertyChangedEventArgs("HasErrors"));
HasErrorsChanged(this, EventArgs.Empty);
}
}
else
{
validation_errors.ForEach(e => error_summary.Append(e.ErrorMessage));
if (Errors.ContainsKey(propertyName))
Errors[propertyName] = error_summary.ToString();
else
Errors.Add(propertyName, error_summary.ToString());
PropertyChanged(this, new PropertyChangedEventArgs("HasErrors"));
HasErrorsChanged(this, EventArgs.Empty);
}
return error_summary.ToString();
}
答案 0 :(得分:2)
我终于找到了我想要的答案。正如我之前所说,如果您输入非法字符,您的财产将永远不会被设置。 WPF框架抛出转换错误异常并将其添加到Validation.Errors集合中,但不会调用任何自定义验证代码。您必须改为使用UpdateSourceExceptionFilter Property。
<TextBox>
<TextBox.Text>
<Binding
UpdateSourceExceptionFilter="ReturnExceptionHandler"
Path="CurrencyPotens"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True"></Binding>
</TextBox.Text>
</TextBox>
在代码隐藏中,我可以将绑定对象强制转换为NotifyPropertyChanged类并添加Error,这反过来会导致我的ICommands CanExecute重新评估。
public object ReturnExceptionHandler(object bindingExpression, Exception exception)
{
BindingExpression be = bindingExpression as BindingExpression;
var boundItem = be.DataItem;
((Wrapper.NotifyPropertyChanged)boundItem).Errors.Add(be.ResolvedSourcePropertyName, exception.Message);
return exception.Message;
}
现在我无法使用我的MVVM方法,因此我在代码隐藏中遇到了一些代码。
答案 1 :(得分:0)
您的代码未被调用,因为UI无法识别是否存在某些错误。我通常做的是在我的VM中实现INotifyDataErrorInfo
。更改属性后,我在属性设置器中调用value
。然后,如果需要,我会解雇INotifyDataErrorInfo.ErrorsChangedEvent
。因此,UI知道错误并做出相应的反应
当然你仍然可以在幕后使用IDataErrorInfo
。希望这有帮助
修改强>
我明白了你的意思。我现在无法找到解决方案,但可能会给你一个方向。我建议查看Overriding metadata technique和Dependency propery callbacks。因此,您覆盖TextBox.TextProperty
元数据并使用自定义回调来设置错误。
当我有空闲时间时,我会回到这个问题