[英]Validation errors block undo
I have the following problem with my EMF based Eclipse application: 我的基于EMF的Eclipse应用程序存在以下问题:
Undo works fine. 撤消工作正常。 Validation works fine. 验证工作正常。 But when there is a validation error for the data in a GUI field, this blocks the use of the undo action . 但是,如果GUI字段中的数据存在验证错误,则会阻止undo操作的使用 。 For example, it is not possible to undo to get back to a valid state for that field. 例如,无法撤消以恢复到该字段的有效状态。
In this picture it is not possible to use undo : 在此图片中,无法使用undo :
Tools that are used in the application: 该应用程序中使用的工具:
UpdateValueStrategy
s on the bindings for validation 绑定上的UpdateValueStrategy
进行验证 UndoAction
that calls CommandStack.undo
使用调用CommandStack.undo
标准UndoAction
实现撤消 MessageManagerSupport
class that connects the validation framework to the Eclipse Forms based GUI. 一个MessageManagerSupport
类,它将验证框架连接到基于Eclipse Forms的GUI。 The data bindings look like this: 数据绑定如下所示:
dataBindingContext.bindValue(WidgetProperties.text(...),
EMFEditProperties.value(...), validatingUpdateStrategy, null);
The problem is this: 问题是这样的:
To make undos work when there are validation errors I think I could do one of these different things: 为了在出现验证错误时使撤消正常工作,我想我可以做以下其中一种不同的事情:
Resource
. 使验证直接在模型上起作用,可能由Resource
上的内容侦听器触发。 (This is a big change of validation strategy. It doesn't seem possible to track the source GUI control in this stage.) (这是验证策略的重大变化。在此阶段似乎无法跟踪源GUI控件。) These solutions either seem impossible or have severe disadvantages. 这些解决方案似乎是不可能的,或者具有严重的缺点。
What is the best way to make undo work even when there are validation errors? 即使存在验证错误,使撤消工作的最佳方法是什么?
NOTE : I accept Mad Matts answer because their suggestions lead me to my solution. 注意 :我接受Mad Matts的回答,因为他们的建议将我引向了我的解决方案。 But I'm not really satisfied with that and I wish there was a better one. 但是我对此并不满意,我希望有更好的解决方案。
If someone at some time finds a better solution I'd be happy to consider to accept it instead of the current one! 如果某人在某个时候找到了更好的解决方案,我很乐意考虑接受它而不是当前的解决方案!
It makes sense that the Validator protects your Target value from invalid values. 验证程序可以保护您的目标值免受无效值的影响。 Therefor the target commandstack remains untouched in case of an invalid value. 因此,在无效值的情况下,目标命令堆栈保持不变。 Why would you like to force invalid values being set? 为什么要强制设置无效值? Isn't ctrl + z
in the GUI enough to reset the last valid state? GUI中的ctrl + z
是否足以重置上一个有效状态?
If you still want to set these values to your actual Target model, you can play around with the UpdateValueStrategy
. 如果您仍想将这些值设置为实际的Target模型,则可以使用UpdateValueStrategy
。
The update phases are: 更新阶段为:
Validate after get - validateAfterGet(Object) 获取后验证-validateAfterGet(Object)
Conversion - convert(Object) 转换-convert(Object)
Validate after conversion - validateAfterConvert(Object) 转换后验证-validateAfterConvert(Object)
Validate before set - validateBeforeSet(Object) 设置之前验证-validateBeforeSet(Object)
Value set - doSet(IObservableValue, Object) 值集-doSet(IObservableValue,Object)
I'm not sure where the validation error ( Status.ERROR
) occurs exactly, but you could check where and then force a SetCommand
manually. 我不确定验证错误( Status.ERROR
)的确切位置,但是您可以检查位置,然后手动强制执行SetCommand
。 You can set custom IValidator
for each step to your UpdateValueStrategy
to do that. 您可以为IValidator
的每个步骤设置自定义UpdateValueStrategy
来执行此操作。
NOTE: This is the solution I ended up using in my application. 注意:这是我最终在应用程序中使用的解决方案。 I'm not really satisfied with it. 我对此并不满意。 I think it is a little bit of a hack. 我认为这有点骇人听闻。
I accept Mad Matts answer because their suggestions lead me to this solution. 我接受Mad Matts的回答,因为他们的建议使我找到了这个解决方案。
If someone at some time finds a better solution I'd be happy to consider to accept it instead of the current one! 如果某人在某个时候找到了更好的解决方案,我很乐意考虑接受它而不是当前的解决方案!
I ended up creating an UpdateValueStratety
sub-class which runs a validator after a value has been set on the model object. 我最终创建了一个UpdateValueStratety
子类,该子类在模型对象上设置了值之后运行验证程序。 This seems to be working fine. 这似乎工作正常。
I create this answer to post the code I ended up using. 我创建此答案以发布最终使用的代码。 Here it is: 这里是:
/**
* An {@link UpdateValueStrategy} that can perform validation AFTER a value is set
* in the model. This is used because undo dosen't work if no model changed in made.
*/
public class LateValidationUpdateValueStrategy extends UpdateValueStrategy {
private IValidator afterSetValidator;
public void setAfterSetValidator(IValidator afterSetValidator) {
this.afterSetValidator = afterSetValidator;
}
@Override
protected IStatus doSet(IObservableValue observableValue, Object value) {
IStatus setStatus = super.doSet(observableValue, value);
if (setStatus.getSeverity() >= IStatus.ERROR || afterSetValidator == null) {
return setStatus;
}
// I used a validator here that calls the EMF generated model validator.
// In that way I can specify validation of the model.
IStatus validStatus = afterSetValidator.validate(value);
// Merge the two statuses
if (setStatus.isOK() && validStatus.isOK()) {
return validStatus;
} else if (!setStatus.isOK() && validStatus.isOK()) {
return setStatus;
} else if (setStatus.isOK() && !validStatus.isOK()) {
return validStatus;
} else {
return new MultiStatus(Activator.PLUGIN_ID, -1,
new IStatus[] { setStatus, validStatus },
setStatus.getMessage() + "; " + validStatus.getMessage(), null);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.