JavaFX中的MVVM。具有数据模型的控件

时间:2016-04-20 06:42:00

标签: design-patterns mvvm javafx

我在fxml文件中定义了一个TableView,但我无法指定表的列,因为该表将具有一些数据模型知识,并且它会违反MVVM。我创建了一个类,它提供了TableColumn的集合并提供了一个数据模型。我想更改相对于表格中所选项目的按钮状态。如何在不违反MVVM规则的情况下做到这一点?

1 个答案:

答案 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> itemsObjectProperty<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视图。