2015-03-13 6 views
5

Ich bin nicht in der Lage, eine Sammlung in fxml an eine benutzerdefinierte Vorlage zu binden. Hier ist der Code, wie ich es in XAML tun würde:JavaFX8-Listenbindungen ähnlich wie 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> 

hier das Modell:

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

, und das Layout aussehen würde, ähnlich wie dies:

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

Ist die Bindung eines oberservable collection zu einer kundenspezifischen Vorlage möglich? Ich probierte die cellfactory, konnte aber meinen Kopf nicht darum wickeln, da jeder nur Saiten benutzte.

+0

Was ist eine benutzerdefinierte Vorlage? – jewelsea

+0

Ich erweiterte meine Frage, um das Setup weiter zu erklären. Was es im Wesentlichen tut, ist, dass für jedes Element in der Sammlung die Vorlage angewendet wird.Für jedes Element in der PersonCollection generiert es also ein horizontales Stackpanel, eine Vornamen-Bezeichnung, eine Nachname-Bezeichnung und eine weitere Listenansicht mit einer Vorlage. – kadir

+0

Wo und wie geben Sie die Eingabedaten an (z. B. John Ivy, Robert Downey Junior usw.)? Ist es statisch und ändert sich niemals oder dynamische Daten, die sich zur Laufzeit ändern? Sind Sie sicher, dass Sie wirklich eine [ListView] (http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/list-view.htm#CEGGEDBF) hier (weil das seltsam wäre) wollen oder Ist das wirklich etwas völlig anderes als ein JavaFX ListView? (Ich habe überhaupt keine Vertrautheit mit XAML). – jewelsea

Antwort

5

Ich bin nicht 100% sicher, dass dies die Antwort auf Ihre Frage ist, wie ich mit XAML völlig fremd bin, aber hoffentlich ist es ...

Beispielimplementierung

Die Probenarbeiten durch die Einstellung Modellobjekt (die Person) in den Namespace des FXML-Loaders, mit dem Sie einen Bindungsausdruck in FXML verwenden können, um an Eigenschaften des Objekts zu binden.

Im Beispiel gibt es zunächst einige Namen im Modell und Sie können die gebundene Liste im Modell ändern, indem Sie die Schaltflächen Hinzufügen und Entfernen verwenden, um einige weitere Namen in der Liste hinzuzufügen oder zu entfernen.

sample image

Alle Code geht in einem Paket mit dem Namen 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); 
    } 
} 

Alternative Implementationen

Es andere sein kann (vielleicht mehr bevorzugte Wege), dies zu tun - zum Beispiel durch Zuordnen von Bindungen von Elementen in Code anstelle von FXML (was ich normalerweise tue) oder durch Injizieren des Modells unter Verwendung eines Abhängigkeitsinjektionssystems. Ein Beispiel für den Injektionsansatz siehe afterburner.fx - obwohl ich nicht weiß, ob der Nachbrenner auch Modellobjekte in den FXML-Namespace platziert oder einfach in den Controller injiziert (falls dies nicht die Injektion in den FXML-Namespace ist) Zusätzlich können Sie es anfordern).

+0

Das ist ähnlich dem Fortschritt, den ich kam, aber ich konnte etwas anderes als Strings nicht vorbereiten. Was ist, wenn ich eine Liste von Buttons oder Panels möchte? Ist das möglich? Ich bin sogar zufrieden mit der Antwort Nr. – kadir

+1

@kadir Dann müssen Sie eine cellFactory angeben. – Puce