JavaFX8列表绑定类似于xaml [英] JavaFX8 list bindings similar to xaml
问题描述
我无法将fxml集合绑定到自定义模板。这里的代码我将如何在xaml中执行:
I am unable to bind in fxml a collection to a customized template. Here the code how I would do it in 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
是否可以将可服务的集合绑定到自定义模板?
我试过了cellfactory,但是我的头不能缠绕它,因为每个人都只使用字符串。
Is the binding of an oberservable collection to a customized template possible? I tried the cellfactory but couldnt get my head wrapped around it, as everybody used only strings.
推荐答案
我是不是100%肯定这是你的问题的答案,因为我完全不熟悉xaml,但希望它是......
I am not 100% sure this is the answer to your question as I am totally unfamiliar with xaml, but hopefully it is...
示例实施
该示例的工作原理是将模型对象(Person)设置为FXML加载器的命名空间,这允许您使用FXML中的绑定表达式绑定到属性物体。
The sample works by setting the model object (the Person) into the namespace of the FXML loader, which allows you to use a binding expression in FXML to bind to properties of the object.
在示例中,模型中最初有几个名称,您可以使用添加和删除按钮修改模型中的绑定列表以添加或删除一些列表中的更多固定名称。
In the sample, there are a few names initially in the model and you can modify the bound list in the model using the add and remove buttons to add or remove a few more canned names in the list.
所有代码都在一个名为sample.names的包中。
All code goes in a package named sample.names.
name-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 - 尽管我不知道加力燃烧室是否也会放置模型对象进入FXML命名空间或只是注入到控制器中(如果它没有注入FXML命名空间,可能是你可以请求它的一个很酷的补充)。
There may be other (perhaps more preferred ways) of doing this - e.g. by associating bindings of items in code rather than FXML (which is what I usually do) or injecting the model using a dependency injection system. See afterburner.fx for an example of the injection approach - though I don't know if afterburner also places model objects into the FXML namespace or just injects into the controller (if it doesn't do the injection into the FXML namespace that might be a cool addition you could request for it).
这篇关于JavaFX8列表绑定类似于xaml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!