JavaFX8列表绑定类似于xaml

时间:2015-03-13 21:18:07

标签: javafx javafx-8 fxml

我无法将fxml集合绑定到自定义模板。这里的代码我将如何在xaml中执行:

<ListView ItemsSource="{Binding PersonCollection}">
    <StackPanel Orientation="Horizontal">
        <Label Content="{Binding FirstName}"></Label>
        <ListView ItemsSource="{Binding MiddleNames}">
            <Label Content="{Binding}"></Label>
        </ListView>
        <Label Content="{Binding LastName}"></Label>
    </StackPanel>
</ListView>

这里的模型:

class Person
{
    String FirstName, LastName;
    String[] MiddleNames;
}

布局看起来与此相似:

John Ivy
Robert Downey Junior
Max more middlenames in fact even thousands are possible lastname

可以将可服务的集合绑定到自定义模板吗? 我尝试了细胞嗅觉,但是不能让我的脑袋缠绕它,因为每个人都只使用细绳。

1 个答案:

答案 0 :(得分:6)

我不是100%肯定这是你问题的答案,因为我对xaml完全不熟悉,但希望它是......

示例实施

该示例通过将模型对象(Person)设置为FXML加载器的命名空间来工作,这允许您使用FXML中的绑定表达式绑定到对象的属性。

在示例中,模型中最初有一些名称,您可以使用添加和删除按钮修改模型中的绑定列表,以在列表中添加或删除一些其他固定名称。

sample image

所有代码都在名为sample.names的包中。

名-display.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.HBox?>

<?import javafx.geometry.Insets?>

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.names.NameDisplayController">
  <HBox prefHeight="150.0" prefWidth="220.0" spacing="5.0"  >
    <children>
      <Label fx:id="firstNameLabel" text="${person.firstName}" />
      <ListView fx:id="middleNameList" prefWidth="100.0" items = "${person.middleNames}" />
      <Label fx:id="lastNameLabel" text="${person.lastName}" />
    </children>
    <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
  </HBox>
  <HBox alignment="CENTER" spacing="30.0">
    <children>
      <Button mnemonicParsing="false" onAction="#addName" text="Add" />
      <Button mnemonicParsing="false" onAction="#removeName" text="Remove" />
    </children>
    <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
    </padding>
  </HBox>
</VBox>

NameDisplayApp.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

import java.io.IOException;

public class NameDisplayApp extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        Person person = new Person(
                "Bruce",
                new String[] { "Simon", "Larry" },
                "Banner"
        );

        FXMLLoader loader = new FXMLLoader(
                getClass().getResource(
                        "name-display.fxml"
                )
        );
        loader.getNamespace().put(
                "person",
                person
        );
        Pane pane = loader.load();

        NameDisplayController controller = loader.getController();
        controller.setPerson(person);

        stage.setScene(new Scene(pane));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

NameDisplayController.java

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

public class NameDisplayController {
    private Person person;

    private ObservableList<String> sampleNames = FXCollections.observableArrayList(
            "George", "Henry", "Wallace"
    );

    public void setPerson(Person person) {
        this.person = person;
    }

    public void addName(ActionEvent actionEvent) {
        if (!sampleNames.isEmpty()) {
            person.getMiddleNames().add(
                sampleNames.remove(0)
            );
        }
    }

    public void removeName(ActionEvent actionEvent) {
        if (!person.getMiddleNames().isEmpty()) {
            sampleNames.add(
                    person.getMiddleNames().remove(0)
            );
        }
    }
}

Person.java

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class Person {
    public StringProperty firstName;
    public StringProperty lastName;

    private ObservableList<String> middleNames;

    public Person(String firstName, String[] middleNames, String lastName) {
        this.firstName   = new SimpleStringProperty(firstName);
        this.middleNames = FXCollections.observableArrayList(middleNames);
        this.lastName    = new SimpleStringProperty(lastName);
    }

    public String getFirstName() {
        return firstName.get();
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName.set(firstName);
    }

    public ObservableList<String> getMiddleNames() {
        return middleNames;
    }

    public String getLastName() {
        return lastName.get();
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName.set(lastName);
    }
}

替代实施

可能有其他(可能更优选的方式)这样做 - 例如通过关联代码中的项目绑定而不是FXML(这是我通常做的)或使用依赖注入系统注入模型。有关注入方法的示例,请参阅afterburner.fx - 虽然我不知道Afterburner是否也将模型对象放入FXML命名空间或仅注入控制器(如果它没有注入FXML命名空间,可能是你可以要求的一个很酷的补充。)