我想用JavaFX创建一个应用程序,我遇到了分离视图(由afterburner.fx分割)和mvvm主体的问题。 在我的场景中,我有一个带有文本字段和按钮的视图和带有列表视图的第二个视图。 现在我在文本字段中编写一些文本,通过单击按钮将文本添加到列表中。 我有四个类(textfield / button和list的视图和视图模型)。 现在问题是:我如何对按钮进行反应并将文本从文本字段传输到列表?
我可以绑定视图中的文本和viewModel中的属性。但是如何将值传递给列表的viewmodel?
我希望有人可以帮助我解决这个理解问题。
非常感谢!
答案 0 :(得分:0)
这里的基本思想是使用单个数据模型,该模型在需要访问共享数据的组件之间共享。在afterburner.fx中使用@Inject
将为您提供一种方便的方法来管理它。
对于设计模式,首先要注意的是afterburner.fx(在较小程度上,也许,FXML - "控制器"机制一般)实际上是基于MVP模式(不是MVVM模式)。 FXML文件代表(被动)视图;演示者当然是演示者,模型是根据应用要求实现的。
通常,您使用的框架是决定使用哪种模式的重要部分,所以我认为我的主要建议是在这里使用MVP模式。使用MVP,如下所示:
您可以在模型中创建ObservableList
:
public class Model {
private final ObservableList<String> itemList = FXCollections.observableArrayList();
public ObservableList<String> getItemList() {
return itemList ;
}
}
然后在具有ListView
的视图的演示者中,执行:
public class ListPresenter {
@Inject
private Model model ;
@FXML
private ListView<String> listView ;
@FXML
public void initialize() {
listView.setItems(model.getItemList());
}
}
以便ListView
使用模型中的ObservableList
作为其项目的后备列表。这意味着如果该列表发生更改,则ListView
将自动更新。
在包含文本字段的视图的演示者中,您执行以下操作:
public class AddItemPresenter {
@Inject
private Model model ;
@FXML
private TextField textField ;
// handler for button press:
@FXML
private void handleButton() {
model.getItemList().add(textField.getText());
}
}
现在按下按钮时,文本字段中的文本将添加到模型的项目列表中。因为您将该列表设置为列表视图的后备列表,所以文本将显示在列表视图中。
如果你想在这里强制使用MVVM模式,我认为你必须考虑&#34; View&#34;在MVVM中包含来自加力燃烧室的FXML-presenter对。因此,您最终得到的东西看起来像M(VP)VM模式。我不像MVC和MVP那样熟悉MVVM,但据我所知,它有三个组件:熟悉的数据模型(M),视图(V)和视图模型(VM)。视图模型的作用是表示视图的状态,包括操作,但它对实际视图本身一无所知。在上面的示例中,您将拥有两个视图模型;每个观点一个。请注意,数据模型(M)仍然存在,当然视图模型需要访问它。他们需要共享相同的数据模型实例,以便他们可以访问和操作相同的数据。
我认为这个实现看起来像
public class ListViewModel {
@Inject
private Model model ;
private final StringProperty selectedItem = new SimpleStringProperty();
public ObservableList<String> getItems() {
return model.getItemList();
}
public StringProperty selectedItemProperty() {
return selectedItem ;
}
public String getSelectedItem() {
return selectedItemProperty().get();
}
public void setSelectedItem(String item) {
selectedItemProperty().set(item);
}
}
Model
类和以前一样。演示者的工作(MVVM中的视图)是将视图绑定到视图模型:
public class ListViewPresenter {
@Inject
private ListViewModel viewModel ;
@FXML
private ListView<String> listView ;
@FXML
public void initialize() {
listView.setItems(viewModel.getItems());
viewModel.selectedItemProperty().bind(listView.getSelectionModel().selectedItemProperty());
}
}
类似于&#34;添加项目的视图模型&#34;模块看起来像
public class AddItemViewModel {
@Inject
private Model model ;
private final StringProperty currentItem = new SimpleStringProperty();
private final Runnable addItemAction = this::addItem ;
public StringProperty currentItemProperty() {
return currentItem ;
}
public String getCurrentItem() {
return currentItemProperty().get();
}
public void setCurrentItem(String item) {
currentItemProperty().set(item);
}
public Runnable getAddItemAction() {
return addItemAction ;
}
private void addItem() {
model.getItemList().add(getCurrentItem());
setCurrentItem("");
}
}
,AddItemPresenter
现在看起来像
public class AddItemPresenter {
@Inject
private AddItemViewModel viewModel ;
@FXML
private TextField textField ;
@FXML
private Button addButton ;
@FXML
public void initialize() {
viewModel.currentItemProperty().bindBidirectional(textField.textProperty());
addButton.setOnAction(e -> viewModel.getAddItemAction().run());
}
}
这里的效果实际上只是在视图和(数据)模型之间插入一个附加层。净效果感觉好像主持人现在并没有真正地减轻它的重量,这通常表明应用程序过度设计并且层数太多。但是,您确实获得了一个优势,因为视图模型现在更加适合测试并且#34;而不是演示者(当然,通过为注入的模型提供setter或构造函数参数可以做得更多)。