我在fxml文件中定义了一个TableView,但我无法指定表的列,因为该表将具有一些数据模型知识,并且它会违反MVVM。我创建了一个类,它提供了TableColumn的集合并提供了一个数据模型。我想更改相对于表格中所选项目的按钮状态。如何在不违反MVVM规则的情况下做到这一点?
答案 0 :(得分:8)
为了解释如何使用MVVM创建表,我使用" Contacts"以表为例。 Contact
类看起来像这样:
class Contact {
private String firstName;
private String lastName;
// Getter/Setters
}
Contact
类是一个实体,属于模型。 MVVM规则说它不应该被View / CodeBehind看到或使用。
相反,我会创建一个包含ContactTableRow
的新类Contact
:
class ContactTableRow {
private Contact contact;
ContactTableRow(Contact contact) {
public String getFirstName() {
return contact.getFirstName();
}
// getter for Lastname
}
从概念上讲,此类属于ViewModel层。对于ViewModels,访问和使用模型类是合法的。
在View类/ CodeBehind中,您现在可以将这个新类用于TableView:
class ContactsView {
@FXML
private TableView<ContactTableRow> table;
}
这也满足了MVVM的规则,因为View可以使用ViewModel类。在您的实际ViewModel中,您现在可以创建ObservableList<ContactTableRow> items
和ObjectProperty<ContactTableRow> selectedItem
:
class ContactViewModel {
private ObservableList<ContactTableRow> items = ...
private ObjectProperty<ContactTableRow> selectedItem = ...
// property accessor methods
}
在View类中,您现在可以将viewModel属性与表视图连接起来,如下所示:
class ContactsView {
@FXML
private TableView<ContactTableRow> table;
private ContactsViewModel viewModel = ...
public void initialize() {
table.setItems(viewModel.itemsProperty());
viewModel.selectedItemProperty().bind(
table.getSelectionModel().selectedItemProperty());
}
现在唯一要做的就是在ViewModel中创建一些逻辑来从数据库加载实际Contact
,将转换为ContactTableRow
个实例并将它们放入items
名单。
使用这种方法,您的View独立于实际的模型类。在这个简单的例子中,它可能看起来像ContactTableRow
类是开销的,但在现实世界的用例中,这可能变得非常有用。它将表与实际的模型类分离。这样,您可以在单个表中显示来自多个entites的数据,如果将来数据结构发生更改,您只需要重构行类而不是整个表。
ViewModel独立于实际的UI特定类。 viewModel提供的是UI应该做什么的抽象定义:有一些数据列表,可以选择这些数据的单个项目。如何向用户显示此数据列表与ViewModel无关。
在不更改ViewModel的情况下,View可以在将来用TableView
或其他组件替换ListView
。
您可以在mvvmFX库的示例部分找到此方法的示例:contacts example包含使用此技术的master-detail视图。