java - 如何在 ViewModel 中设置验证检查

标签 java javafx javafx-2 javafx-8

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

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

    public PersonViewModel() {}

    // getters and setters
}

和简单的 View :

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既可以过滤文本输入控件中的输入,也可以将文本转换为特定类型的值。如果您希望 View 模型定义验证规则,请在其中定义一个表示验证的方法,并在 TextFormatter 的过滤器定义中委托(delegate)给该方法。 。例如:

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());
    }
}

此处定义的过滤器仅接受控件中的输入(如果它与 PersonViewModel 中的方法定义的规则匹配)。 。 valueProperty() TextFormatter的代表 TextField 中的文本将其传递给 IntegerStringConverter 后:这双向绑定(bind)到 ageProperty()在模型中。 (对 asObject() 的调用实际上只是在 IntegerPropertyObjectProperty<Integer> 之间进行转换。)

关于java - 如何在 ViewModel 中设置验证检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32091476/

相关文章:

java - jackson 无法用连字符反序列化字段

java - FirefoxDriver : how to disable javascript, css 并使 sendKeys 立即键入?

java - ListView细胞工厂: wrong font weight

java - 如何在不使用静态上下文中的类名的情况下访问 java 中的 .class 对象

java - Gson排除策略和自定义序列化

JavaFX "y"在 Canvas 上的位置

java - 如何将 TableCell 样式类绑定(bind)到 TableRow 样式类 (JavaFX)

java - 为什么我在尝试运行 JavaFx 应用程序时出现 java.lang.ClassNotFoundException?

javafx-2 - 引用外部 jar 的 JavaFx 2.0 应用程序

javafx-2 - 如何更改标签字体的大小以获取最大尺寸