我的基于EMF的Eclipse应用程序存在以下问题:
撤消工作正常。验证工作正常。但是,当GUI字段中的数据存在验证错误时,会阻止使用撤消操作。例如,无法撤消以返回该字段的有效状态。
在此图片中,无法使用撤消:
应用程序中使用的工具:
UpdateValueStrategy
关于验证的绑定UndoAction
CommandStack.undo
实现的
MessageManagerSupport
类。数据绑定如下所示:
dataBindingContext.bindValue(WidgetProperties.text(...),
EMFEditProperties.value(...), validatingUpdateStrategy, null);
问题在于:
要在验证错误时使undos正常工作,我想我可以做其中一件事:
Resource
上的内容侦听器触发。 (这是验证策略的一个重大变化。在这个阶段似乎无法跟踪源GUI控件。) 这些解决方案似乎不可能或有严重的缺点。
即使存在验证错误,撤消工作的最佳方法是什么?
注意:我接受Mad Matts的回答,因为他们的建议引导我找到解决方案。但我对此并不满意,我希望有一个更好的。
如果有人在某个时间找到了更好的解决方案,我很乐意考虑接受它而不是当前的解决方案!
答案 0 :(得分:1)
Validator可以保护您的Target值不受无效值的影响。
因此,在值无效的情况下,目标命令堆保持不变。
您为什么要强制设置无效值? GUI中的ctrl + z
是否足以重置上一个有效状态?
如果您仍想将这些值设置为实际的目标模型,则可以使用UpdateValueStrategy
。
更新阶段是:
- 之后验证
在get - validateAfterGet(Object)
转换 - 转换(对象)
转换后验证 - validateAfterConvert(Object)
在设置之前验证 - validateBeforeSet(Object)
- 醇>
值集 - doSet(IObservableValue,Object)
我不确定验证错误(Status.ERROR
)的确切位置,但您可以检查位置,然后手动强制SetCommand
。
您可以为IValidator
的每个步骤设置自定义UpdateValueStrategy
来执行此操作。
答案 1 :(得分:1)
注意:这是我最终在我的应用程序中使用的解决方案。我对此并不满意。我认为这有点像黑客。
我接受Mad Matts的回答,因为他们的建议引导我解决这个问题。
如果有人在某个时间找到了更好的解决方案,我会很乐意考虑接受它而不是当前的解决方案!
我最终创建了一个UpdateValueStratety
子类,在模型对象上设置了值后,运行验证器。这似乎工作正常。
我创建这个答案来发布我最终使用的代码。这是:
/**
* 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);
}
}
}