Java 如何在ViewModel中设置验证检查

Java 如何在ViewModel中设置验证检查,java,javafx,javafx-2,javafx-8,Java,Javafx,Javafx 2,Javafx 8,我是构建JavaFXMVVM应用程序的新手。 我创建了一个简单的ViewModel: public class PersonViewModel { private final StringProperty name = new SimpleStringProperty(); private final IntegerProperty age = new SimpleIntegerProperty(); public PersonViewModel() {} /

我是构建JavaFXMVVM应用程序的新手。 我创建了一个简单的ViewModel:

public class PersonViewModel {
    private final StringProperty name = new SimpleStringProperty();
    private final IntegerProperty age = new SimpleIntegerProperty();

    public PersonViewModel() {}

    // getters and setters
}
和简单视图:

public class PersonView implements Initializable {
    @FXML
    TextField name;

    @FXML
    TextField age;

    @FXML
    Button ok;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        PersonViewModel viewModel = new PersonViewModel();
        name.textProperty().bindBidirectional(viewModel.name);
        age.textProperty().bindBidirectional(viewModel.age);
    }
}
你能告诉我如何进行年龄验证吗?F.e.我不想允许用户在年龄(文本字段)中输入字符,除了[a-zA-Z]。我的问题的主要思想是在ViewModel中进行验证)请帮助我


另外,我希望不要使用非标准的javafx组件。

您可以使用
TextFormatter
来过滤文本输入控件中的输入,并将文本转换为特定类型的值。如果希望视图模型定义验证规则,请在其中定义表示验证的方法,并在
TextFormatter
的过滤器定义中委托给该方法。例如:

public class PersonViewModel {

    private final StringProperty name = new SimpleStringProperty();

    public StringProperty nameProperty() {
        return name ;
    }
    public final String getName() {
        return nameProperty().get();
    }
    public final void setName(String name) {
        nameProperty.set(name);
    }

    private final IntegerProperty age = new SimpleIntegerProperty();
    public IntegerProperty ageProperty() {
        return age ;
    }
    public final int getAge() {
        return ageProperty().get();
    }
    public final void setAge(int age) {
        ageProperty.set(age);
    }

    public boolean validAgeInput(String input) {
        // must support partial entry while editing, including empty string
        // accept any integer from 0 - 135 (arbitrary upper bound example)
        String regex = "([0-9]{0,2})|(1[0-2][0-9])|(13[0-5])";
        return input.matches(regex);
    }

}
现在您可以执行以下操作:

public class PersonView implements Initializable {
    @FXML
    TextField name;

    @FXML
    TextField age;

    @FXML
    Button ok;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        PersonViewModel viewModel = new PersonViewModel();
        UnaryOperator<Change> filter = change -> {
            if (viewModel.validAgeInput(change.getControlNewText()) {
                // accept
                return change ;
            } else {
                // reject
                return null ;
            }
        };
        TextFormatter<Integer> ageFormatter = new TextFormatter<>(new IntegerStringConverter(), 0, filter);
        age.setTextFormatter(ageFormatter);
        ageFormatter.valueProperty().bindBidirectional(viewModel.ageProperty().asObject());
        name.textProperty().bindBidirectional(viewModel.nameProperty());
    }
}
公共类PersonView实现了可初始化{
@FXML
文本字段名称;
@FXML
文本场年龄;
@FXML
按钮ok;
@凌驾
公共void初始化(URL位置、ResourceBundle资源){
PersonViewModel viewModel=新PersonViewModel();
一元运算符筛选器=更改->{
if(viewModel.validAgeInput(change.getControlNewText()){
//接受
回报变化;
}否则{
//拒绝
返回null;
}
};
TextFormatter ageFormatter=新的TextFormatter(新的IntegerStringConverter(),0,过滤器);
age.setTextFormatter(ageFormatter);
ageFormatter.valueProperty().BindDirective(viewModel.ageProperty().asObject());
name.textProperty().bindproductive(viewModel.nameProperty());
}
}
此处定义的筛选器仅在与
PersonViewModel
中的方法定义的规则匹配时才接受控件中的输入
TextFormatter
的表示将文本传递给
IntegerStringConverter
后的
TextField
中的文本:该文本双向绑定到模型中的
ageProperty()
(对
asObject()的调用)
有效地只是在
IntegerProperty
ObjectProperty
之间转换)