我想创建输入表单来验证用户输入并防止模型与无效数据一起保存。我一直在使用数据绑定,但是我的实现并不像我想的那样直观。
想象一下包含' 123'的输入。并且值不能为空。用户逐个删除字符直到空。数据绑定验证器显示错误修饰。
但是,如果用户保存表单并重新加载,那么' 1'显示在字段中 - 即最后一个有效输入。数据绑定不会将无效值传输到模型中。
我有一个ChangeListener但是在数据绑定之前调用它,所以此时没有检测到无效状态。
我希望错误显示在UI中,但模型仍然有效(已经是这样)。此外,只要UI包含错误,就不可能保存模型。
/**
* Bind a text control to a property in the view model
**/
protected Binding bindText(DataBindingContext ctx, Control control,
Object viewModel, String property, IValidator validator)
{
IObservableValue value = WidgetProperties.text(SWT.Modify).observe(
control);
IObservableValue modelValue = BeanProperties.value(
viewModel.getClass(), property).observe(viewModel);
Binding binding = ctx.bindValue(value, modelValue, getStrategy(validator), null);
binding.getTarget().addChangeListener(listener);
ControlDecorationSupport.create(binding, SWT.TOP | SWT.LEFT);
return binding;
}
private UpdateValueStrategy getStrategy(IValidator validator)
{
if (validator == null)
return null;
UpdateValueStrategy strategy = new UpdateValueStrategy();
strategy.setBeforeSetValidator(validator);
return strategy;
}
private IChangeListener listener = new IChangeListener()
{
@Override
public void handleChange(ChangeEvent event)
{
// notify all form listeners that something has changed
}
};
/**
* Called by form owner to check if the form contains valid data e.g. before saving
**/
public boolean isValid()
{
System.out.println("isValid");
for (Object o : getDataContext().getValidationStatusProviders())
{
ValidationStatusProvider vsp = (ValidationStatusProvider) o;
IStatus status = (IStatus)vsp.getValidationStatus()
.getValue();
if (status.matches(IStatus.ERROR))
return false;
}
return true;
}
答案 0 :(得分:2)
你最好的选择是避开ChangeListener
- 正如你所发现的那样,他们的执行顺序要么未定义,要么在这种情况下没有帮助。
相反,你想要尽可能长时间地坚持'可观察'而不是'听众'模式。如前所述,创建AggregateValidationStatus
以收听DataBindingContext
的整体状态,其效果与现有代码类似。
然后你可以直接听(如下所示)来影响保存能力,或者你甚至可以将它绑定到另一个bean。
IObservableValue statusValue = new AggregateValidationStatus(dbc, AggregateValidationStatus. MAX_SEVERITY);
statusValue.addListener(new IValueChangeListener() {
handleValueChange(ValueChangeEvent event) {
// change ability to save here...
}
});
答案 1 :(得分:1)
您可以使用AggregateValidationStatus
来观察汇总验证状态:
IObservableValue value = new AggregateValidationStatus(bindContext.getBindings(),
AggregateValidationStatus.MAX_SEVERITY);
您可以将此绑定到接受IStatus
参数的内容,并且每次验证状态更改时都会调用它。