2013-07-11 6 views
5

Ich habe Probleme, die Datenbindung in meiner Eclipse RCP-Anwendung zu verstehen. Ich kann einfach nicht herausfinden, wie es sollte arbeiten ..Bewährtes Verfahren zum Binden einer Liste in der Eclipse RCP-Anwendung

Hier ist, was ich

ich einen Blick zu tun haben will, wo eine Liste der Texte angezeigt werden soll. Die Texte werden in einer einfachen List<String> "gespeichert", die über einen Singleton bereitgestellt wird (nur zu Demonstrationszwecken;)). Wer also ListProvider benutzt, bekommt die Liste der Texte. Wenn sich die Liste ändert, möchte ich, dass meine Ansicht den Inhalt der Tabelle automatisch aktualisiert.

Hier ist, was ich bisher getan habe

My List-Provider ist ein Observable, die Beobachter, wenn die Liste Änderungen in Kenntnis setzen wird.

Meiner Ansicht nach erstelle ich einen Observer, um den Listenanbieter zu beobachten, und wenn der Beobachter benachrichtigt wird, aktualisiere ich meine Ansicht.

-Code für die ListProvider:

public class ListProvider extends Observable { 

    private Stack<String> hist; 
    private static ListProvider instance; 

    // Singleton implementation 
    public static ListProvidergetInstance() { 
     if (null == instance) { 
      instance = new ListProvider 
     } 
     return instance; 
    } 

    public void add(String text) { 
     if (this.hist.size() == MAX_SIZE) { 
      this.hist.remove(MAX_SIZE-1); 
     } 
     this.hist.add(0, text); 
     // notify all observers 
     this.setChanged(); 
     this.notifyObservers(); 
    } 
} 

-Code für die Ansicht:

public class TestView extends ViewPart { 

private TableViewer viewer; 

[...] 

class ViewContentProvider implements IStructuredContentProvider { 
    public void inputChanged(Viewer v, Object oldInput, Object newInput) { 
    } 
    public void dispose() { 
    } 
    public Object[] getElements(Object parent) { 
     return ClipboardHistory.getInstance().getList().toArray(); 
    } 
} 

public void createPartControl(Composite parent) { 
    viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); 
    IContentProvider contentProvider = new ViewContentProvider(); 
    viewer.setContentProvider(contentProvider); 
    viewer.setLabelProvider(new ViewLabelProvider()); 
    viewer.setInput(getViewSite()); 

    Observer listObserver = new Observer() { 
     @Override 
     public void update(Observable o, Object arg) { 
      // update the table viewer 
      viewer.refresh(); 
     } 
    }; 

    ListProvider.getInstance().addObserver(listObserver); 
} 
} 

Frage

Nutzt Observer und Observable die "richtige" Art und Weise bin zu gehen oder ich etwas vermissen? Ich bin mir nicht sicher, ob ich das Konzept von RCP Databinding verstanden habe ...

+0

Ich bin mir nicht sicher über den Umfang der Elemente in Ihrer Liste, aber haben Sie in Betracht gezogen, eine einfache SWT-Liste (http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.platform .doc.isv% 2Freferenz% 2Fapi% 2Forg% 2Feclipse% 2Fswt% 2Fwidgets% 2FList.html) Objekt zu Ihrer Ansicht anstelle eines Tableviewers etc etc – nbz

+0

Auch könnte es besser sein, einen ListViewer zu verwenden (http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc. isv% 2Freferenz% 2Fapi% 2Forg% 2Feclipse% 2Fjface% 2Fviewers% 2FListViewer.html) anstelle eines TableViewers. – nbz

+0

Danke für die Eingabe. Im Moment ist es nur eine Liste, aber ich möchte später weitere Daten zu anderen Spalten hinzufügen. Würde die Verwendung eines ListViewer die Art ändern, wie ich die Liste beobachte? – Friederike

Antwort

5

Ich empfehle Ihnen JFace Databinding Lesen und die Verwendung von ViewerSupport, ObservableListContentProvider machen und BeanProperties, um den Job zu vereinfachen.

Sie können auch ein funktionierendes Beispiel JFace Databinding Snippet: Model to TableViewer binding für eine Referenz sehen, wo die Bindung zuletzt mit Hilfe von ViewerSupport getan wird:

(...) 
TableViewer peopleViewer = new TableViewer(committers); 
ViewerSupport.bind(peopleViewer, new WritableList(viewModel.getPeople(), 
    Person.class), BeanProperties.value(Person.class, "name")); 

Mit diesen Helfer brauchen Sie nicht die Observer für Ihre umzusetzen Wenn Sie möchten, dass der Viewer seine Beschriftungen aktualisiert, wenn Daten geändert werden, sehen Sie im selben Beispiel nach PropertyChangeSupport, mit dem Sie den Viewer bei jeder Änderung an einem Element der Liste aktualisieren können, die Sie darüber informieren. Es ist wichtig, dass Sie BeanProperties für die Bindung verwenden.

+0

Das scheint eine gute Lösung zu sein. Aber gibt es eine Möglichkeit, Validatoren und Konverter mit einem Table Viewer zu verwenden? – Lii

1

Ich glaube nicht, dass irgendetwas mit Ihrer Herangehensweise falsch ist, mit einer möglichen Ausnahme. Sie müssen sicherstellen, dass der Betrachter in dem UI-Thread aktualisiert wird:

Display.getDefault().asyncExec(new Runnable() { 
    @Override 
    public void run() { 
     viewer.refresh(); 
    } 
}); 

Allerdings gibt Dinge, die Sie tun können, die Tabellenaktualisierung effizienter zu machen. In Ihrem Code oben scheint es nur ein einzelnes Element an der Spitze der Tabelle hinzufügen, so würden Sie mit einem Anruf besser sein:

viewer.insert(text, 0); 
+0

Danke für den Hinweis auf dem UI-Thread. Was die Optimierung mit 'viewer.insert' angeht, denke ich nicht, dass es effizienter ist. Ich kann nicht sicher sein, welche Änderungen an meinem Modell vorgenommen wurden. Also müsste ich nach Updates/Einfügungen/Löschungen suchen. Das ist viel teurer als nur die ganze Liste wieder zu bekommen und anzuzeigen. ;) – Friederike