如何在 ViewModel 中设置验证检查
How to set validation check in ViewModel
我是构建 javafx MVVM 应用程序的新手。
我创建了一个简单的 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],我不想让用户将字符放入年龄(TextField)中。我的问题的主要思想是在 ViewModel 中进行此验证)请帮助我。
P.S。我想让它不使用非标准的 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());
}
}
此处定义的过滤器只有在匹配PersonViewModel
中的方法定义的规则时才会接受控件中的输入。 TextFormatter
的 valueProperty()
表示 TextField
传递给 IntegerStringConverter
后的文本:它双向绑定到模型中的 ageProperty()
。 (对 asObject()
的调用实际上只是在 IntegerProperty
和 ObjectProperty<Integer>
之间转换。)
我是构建 javafx MVVM 应用程序的新手。 我创建了一个简单的 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],我不想让用户将字符放入年龄(TextField)中。我的问题的主要思想是在 ViewModel 中进行此验证)请帮助我。
P.S。我想让它不使用非标准的 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());
}
}
此处定义的过滤器只有在匹配PersonViewModel
中的方法定义的规则时才会接受控件中的输入。 TextFormatter
的 valueProperty()
表示 TextField
传递给 IntegerStringConverter
后的文本:它双向绑定到模型中的 ageProperty()
。 (对 asObject()
的调用实际上只是在 IntegerProperty
和 ObjectProperty<Integer>
之间转换。)