8 Replies Latest reply: Nov 28, 2012 11:00 PM by Sai Pradeep Dandem RSS

    How to use ListBinding ?

    Sai Pradeep Dandem
      Hi,
      I have a requirement where I want to use ListBinding.
      I have an observable list of objects (say Employee.java which contains id, firstName, Lastname as its properties.)
      I want to bind/create all the firstName s to a separate list, by using binding to the main list of objects.

      So that
      * Whenever a new Employee object is added into main list, the second list also updates automatically.
      * Whenever the firstName of any Employee object is modified in the main list, the second list also updates accordingly.

      Can I get the second list (List of firstName s) by using ListBinding.? If yes can anyone please give some inputs how to achieve this.?

      Thanks in advance !!


      Regards,
      Sai Pradeep Dandem.
        • 1. Re: How to use ListBinding ?
          975590
          Hi,

          I am not sure if I have understood your meaning :)
          You want to get a list(list 1) which only has "firstName" from a list(list 2) which has the whole objects, and list 1 can be changed when list 2 is changed?

          The list here you mean is just a kind of data structrue? or it is ListView?
          If you mean ListView, I think it may be a simple question. :)
          • 2. Re: How to use ListBinding ?
            Sai Pradeep Dandem
            Hi,
            Sorry for the confusion.

            I want to get an ObservableList(list-1) which only has "firstName" from another ObservableList(list-2) which has the whole Employee objects, and list-1 can be changed when list-2 is changed?

            In other words I want to maintain list-1 by using binding with list-2.(may be ListBinding)

            Thanks & Regards,
            Sai Pradeep Dandem.
            • 3. Re: How to use ListBinding ?
              975590
              Hi,

              I am sorry that I don't have any idea about ListBinding.
              (Maybe you can implement it by using observer design pattern, register list-1 to list-2, when list-2 changes, notice list-1, and let list-1 do the same kind changes~~haa, it sounds like a "stupid" method, there exists ObservableList already! :) )

              Hope someone else will help you!
              • 4. Re: How to use ListBinding ?
                James_D
                What are your exact requirements here?

                If you want a plain old java.util.List<String> for your list of first names, then your best bet is probably not to use binding at all, but to define a wrapper class that implements List<String> and simply references into the List<Person> for its accessor methods. This might be as simple as
                import java.util.AbstractList;
                import javafx.collections.ObservableList;
                
                public class FirstNameList extends AbstractList<String> {
                  private final ObservableList<Person> personList ;
                  public FirstNameList(ObservableList<Person> personList) {
                    this.personList = personList ;
                  }
                  @Override
                  public String get(int index) {
                    return personList.get(index).getFirstName();
                  }
                  @Override
                  public int size() {
                    return personList.size();
                  }
                }
                If you want an ObservableList<String> for your list of first names, the same approach should work, but managing listener notification on the wrapper might be somewhat tricky.

                If you're using the list of first names just to display in another control (the most common use case for needing an ObservableList), then the best bet might be to make the control reference your ObservableList<Person> and customize the control's cells to only display the first name.

                Edited by: James_D on Nov 28, 2012 5:21 AM (Added code example)
                • 5. Re: How to use ListBinding ?
                  shakir.gusaroff
                  Hi. There is Bindings. bindContentBidirectional(list1, list2);
                  But list1 and list2 should be the same type of object. This is not appropriate for you.
                  I think for your case Map is more suitable.
                  Key: Employee.firstname
                  Value:Employee
                  Then add a mapchangeListener to your ObservableMap
                  http://docs.oracle.com/javafx/2/api/javafx/collections/MapChangeListener.html
                  • 6. Re: How to use ListBinding ?
                    James_D
                    Ah, even with the simple FirstNameList I made above, you can (sort of) create an ObservableList<String> from it. It's not very efficient, because the list is rebuilt on each change, but it should work.
                    final ObservableList<Person> data = ... ;
                    final List<String> firstNames = new FirstNameList(data);
                    ObservableList<String> observableFirstNames = new ListBinding<String>() {
                      { super.bind(data); }
                      protected ObservableList<String> computeValue() {
                         return FXCollections.observableArrayList(firstNames);
                      }
                    };
                    • 7. Re: How to use ListBinding ?
                      James_D
                      At some point, I might actually learn to think everything through before posting a single solution, instead of incrementally making my solutions better.

                      I made a more general version of the whole thing. Here's a DependentList<T,S> which implements a list of type S, based on a list of type T. You specify a Callback<T,S> to determine how to get an element of type S from an element of type T in the original list. In your case T is Employee, S is String, and the Callback is implemented as

                      return employee.getFirstName();

                      DependentList.java
                      import java.util.AbstractList;
                      import java.util.List;
                      
                      import javafx.beans.binding.ListBinding;
                      import javafx.collections.FXCollections;
                      import javafx.collections.ListChangeListener;
                      import javafx.collections.ObservableList;
                      import javafx.util.Callback;
                      
                      public class DependentList<T, S> extends AbstractList<S> {
                        
                        private final ObservableList<T> data ;
                        private final Callback<T,S> callback ;
                        private final ListBinding<S> binding ;
                        
                        public DependentList(ObservableList<T> data, Callback<T, S> callback) {
                          this.data = data ;
                          this.callback = callback ;
                          this.binding = new ListBinding<S>() {
                            {super.bind(DependentList.this.data);}
                            @Override
                            protected ObservableList<S> computeValue() {
                              return FXCollections.observableArrayList(DependentList.this);
                            }
                          };
                        }
                      
                        @Override
                        public S get(int index) {
                          return callback.call(data.get(index));
                        }
                      
                        @Override
                        public int size() {
                          return data.size();
                        }
                        
                        // TODO: not a very efficient implementation
                        public ObservableList<S> asObservableList() {
                          return binding ;
                        }
                        
                      }
                      Usage example:
                          ObservableList<Person> personList = FXCollections.observableArrayList(); // populate
                      
                          // To get a List of the firstNames:
                      
                          List<String> firstNameList = new DependentList<Person, String>(personList, new Callback<Person, String>() {
                            @Override
                            public String call(Person person) {
                              return person.getFirstName();
                            }
                          });
                      
                          // To get an ObservableList of the firstNames:
                      
                          ObservableList<String> observableFirstNames = new DependentList<Person, String>(personList, new Callback<Person, String>() {
                            @Override
                            public String call(Person person) {
                              return person.getFirstName();
                            }
                          }).asObservableList();
                      • 8. Re: How to use ListBinding ?
                        Sai Pradeep Dandem
                        Hi James,
                        Thanks for your inputs :)
                        I will check this whether it will solve my requirement. Thanks a lot !! :)

                        Thanks & Regards,
                        Sai Pradeep Dandem.