EMF - EditingDomain/CommandStack

Hallo mal wieder,

hab mich nach meinen letzten Fragen etwas mehr in die Materie eingelesen und auch schon einige Dinge auf die Reihe bekommen. Jetzt steh ich grad vor dem Problem, dass ich meine bisher direkten Bindings gerne dahingehend ändern würde, dass alles über einen CommandStack läuft, um z.B. eine Speichern/Verwerfen Funktionalität zu bekommen.

Hier mal eine meiner Klassen, sie stellt ein Composite zur Verfügung, in der eine meiner EMF-Klassen bearbeitet werden kann (Stammdaten). Hat den Hintergrund, dass dieses Composite dann je nach dem auf ner View oder einem Dialog oder wo auch immer platziert wird, und das übergebene Objekt bearbeiten soll.

Java:
public class EditStammdatenPanel extends EditDefault{

	private Text txtVorname;
	private Text txtNachname;
	private DateTime dtGeburtsdatum;
	private Text txtEmail;
	
	private Combo cmbStaatsbuergerschaft;
	private ComboViewer cvStaatsbuergerschaft;

	private Combo cmbAnrede;
	private ComboViewer cmbViewer;
	
	private ObservableListContentProvider obsListContentProvider;
	
	public EditStammdatenPanel(Composite _parent, Person _aktPerson, int _spaltenDesPanels) {
		super(_parent, _aktPerson);
		createPanel(_spaltenDesPanels);
	}
	
	public EditStammdatenPanel(Composite _parent, Person _aktPerson, int _spaltenDesPanels, EMFDataBindingContext _emfDataBindingContext) {
		this(_parent, _aktPerson, _spaltenDesPanels);
		emfDataBindingContext = _emfDataBindingContext;
	}
	
	private void createPanel(int spaltenAnzahl) {
		
		Label lblAnrede = new Label(parent, SWT.NONE);
		lblAnrede.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblAnrede.setText("Anrede");
		
		cmbViewer = new ComboViewer(parent, SWT.READ_ONLY);
		cmbViewer.setContentProvider(new ArrayContentProvider());
		cmbViewer.setInput(Anrede.values());
		cmbAnrede = cmbViewer.getCombo();
		cmbAnrede.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		if(spaltenAnzahl == 4) {
			new Label(parent, SWT.NONE);
			new Label(parent, SWT.NONE);
		}
		
		Label lblVorname = new Label(parent, SWT.NONE);
		lblVorname.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblVorname.setText("Vorname");
		
		txtVorname = new Text(parent, SWT.BORDER);
		txtVorname.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		
		Label lblNachname = new Label(parent, SWT.NONE);
		lblNachname.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblNachname.setText("Nachname");
		
		txtNachname = new Text(parent, SWT.BORDER);
		txtNachname.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		
		Label lblGeburtsdatum = new Label(parent, SWT.NONE);
		lblGeburtsdatum.setText("Geburtsdatum");
		
		dtGeburtsdatum = new DateTime(parent, SWT.BORDER | SWT.DROP_DOWN);
		GridData gd_dtGeburtsdatum = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
		gd_dtGeburtsdatum.widthHint = 118;
		dtGeburtsdatum.setLayoutData(gd_dtGeburtsdatum);
		
		Label lblStaatsbrgerschaft = new Label(parent, SWT.NONE);
		lblStaatsbrgerschaft.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblStaatsbrgerschaft.setText("Staatsb\u00FCrgerschaft");
		
		cvStaatsbuergerschaft = new ComboViewer(parent, SWT.READ_ONLY);
		obsListContentProvider = new ObservableListContentProvider();
		cvStaatsbuergerschaft.setContentProvider(obsListContentProvider);
		cmbStaatsbuergerschaft = cvStaatsbuergerschaft.getCombo();
		cmbStaatsbuergerschaft.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		
		Label lblEmail = new Label(parent, SWT.NONE);
		lblEmail.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblEmail.setText("Email");
		
		txtEmail = new Text(parent, SWT.BORDER);
		txtEmail.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		new Label(parent, SWT.NONE);
		new Label(parent, SWT.NONE);
		
	}
	
	@Override
	protected void initDataBindings() {

		if(emfDataBindingContext == null)
			emfDataBindingContext = new EMFDataBindingContext();
		
		IValueProperty valProp = ViewerProperties.singleSelection();
		IEMFValueProperty emfValProp = EMFProperties.value(MitgliederPackage.Literals.PERSON__ANREDE);
		emfDataBindingContext.bindValue(valProp.observe(cmbViewer), emfValProp.observe(aktPerson));
		//
		IObservableValue swtObsVal = SWTObservables.observeText(txtVorname, SWT.Modify);
		IObservableValue emfObsVal = EMFObservables.observeValue(aktPerson, Literals.PERSON__VORNAME);
		System.out.println(aktPerson.toString());
		emfDataBindingContext.bindValue(swtObsVal, emfObsVal, null, null);
		//
		swtObsVal = SWTObservables.observeText(txtNachname, SWT.Modify);
		emfObsVal = EMFObservables.observeValue(aktPerson, Literals.PERSON__NACHNAME);
		emfDataBindingContext.bindValue(swtObsVal, emfObsVal, null, null);
		//
		swtObsVal = SWTObservables.observeText(txtEmail, SWT.Modify);
		emfObsVal = EMFObservables.observeValue(aktPerson, Literals.PERSON__EMAIL);
		emfDataBindingContext.bindValue(swtObsVal, emfObsVal, null, null);
		//
		//
		swtObsVal = SWTObservables.observeSelection(dtGeburtsdatum);
		emfValProp = EMFProperties.value(MitgliederPackage.Literals.PERSON__GEBURTSDATUM);
		emfDataBindingContext.bindValue(swtObsVal, emfValProp.observe(aktPerson));
		//
		//
		IObservableMap obsMap = EMFProperties.value(Literals.LAND__NAME).observeDetail(obsListContentProvider.getKnownElements());
		cvStaatsbuergerschaft.setLabelProvider(new ObservableMapLabelProvider(obsMap));
		IEMFListProperty listProp = EMFProperties.list(Literals.LAENDER__LIST_LAENDER);
		cvStaatsbuergerschaft.setInput(listProp.observe(laender));
		emfValProp = EMFProperties.value(Literals.PERSON__STAATSBUERGERSCHAFT);
		valProp = ViewerProperties.singleSelection();
		emfDataBindingContext.bindValue(valProp.observe(cvStaatsbuergerschaft),emfValProp.observe(aktPerson));
	}

	@Override
	public void doBinding(Person _Person, EMFDataBindingContext _emfDataBindingContext) {
		aktPerson = _Person;
		
		if(emfDataBindingContext != null)
			emfDataBindingContext.dispose();
		
		emfDataBindingContext = _emfDataBindingContext;
		initDataBindings();
	}
}
Java:
public abstract class EditDefault {

	protected Composite parent;
	
	protected Person aktPerson;
	protected Laender laender;
	
	protected EMFDataBindingContext emfDataBindingContext;
	
	public EditDefault(Composite _parent, Person _aktPerson) {
		parent = _parent;
		aktPerson = _aktPerson;
		laender = ModelProvider.INSTANCE.getLaender();
	}
	
	protected abstract void initDataBindings();
	public abstract void doBinding(Person _Person, EMFDataBindingContext _emfDataBindingContext);
	
	public void setParent(Composite _parent) {
		parent = _parent;
	}
	
	public Composite getParent() {
		return parent;
	}
	
	public void setEMFDataBindingContext(EMFDataBindingContext _emfDBC) {
		emfDataBindingContext = _emfDBC;
	}
	
	public EMFDataBindingContext getEMFDataBindingContext() {
		return emfDataBindingContext;
	}
	
	public void setPerson(Person p) {
		aktPerson = p;
	}
	
	public Person getPerson() {
		return aktPerson;
	}
}
Fragen dazu:
- Gibt es wo eine verständlichere Anleitung als das, was auf Tom Schindls Blog ist? Das war mir etwas zu weit verzahnt, als dass ich es problemlos verstanden hätte...
Ein simples Beispiel mit Person Vorname/Nachname und einer View, wo beides mittels "Speichern" verarbeitet wird, würde auch voll reichen... nur das was ich bisher gesehn hab, war mir zu komplex :(
- Ist der restliche Ansatz mit dem Databinding richtig, oder mache ich hier auch irgendwo Fehler? Funktionieren tut alles wie gewünscht, aber ich weiss nicht, ob ich nicht eventuell daten irgendwie am Modell vorbeischmuggle oder so...

Zusatzfrage:
Ich hab in meinem Modell eine Länder Klasse, welche eine Liste aus einzelnen Land objekten hält. Diese benutze ich, um alle möglichen Links herzustellen wie Staatsbürgerschaft, Telefonvorwahlen, etc. Um auf diese Länder-Liste zugreifen zu können, habe ich sie in einen kleinen Model-Provvider ausgelagert... Ich weiss nur nicht, ob das Sinnvoll ist, oder ob ich auch ohne diesen Umweg irgendwie direkt auf die Daten es EMF-Modells zugreifen könnte...

Java:
public enum ModelProvider {
	INSTANCE;
	
	private Mitglieder mitglieder;
	private Laender laender;
	final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
	
	private ModelProvider() {
		mitglieder = MitgliederFactory.eINSTANCE.createMitglieder();
		
		laender = MitgliederFactory.eINSTANCE.createLaender();
		
		Land at = MitgliederFactory.eINSTANCE.createLand();
		at.setFahne("at");
		at.setName("Österreich");
		at.setVorwahl("+43");
		laender.getListLaender().add(at);
		
		Land de = MitgliederFactory.eINSTANCE.createLand();
		de.setFahne("de");
		de.setName("Deutschland");
		de.setVorwahl("+49");
		laender.getListLaender().add(de);
		
		Adresse adr = MitgliederFactory.eINSTANCE.createAdresse();
		adr.setAdressart(Adressarten.HAUPTWOHNSITZ);
		adr.setStrasse("111");
		adr.setPlz("222");
		adr.setOrt("333");
		adr.setLand(laender.getListLaender().get(0));
		
		Adresse adr2 = MitgliederFactory.eINSTANCE.createAdresse();
		adr2.setAdressart(Adressarten.ZWEITWOHNSITZ);
		adr2.setStrasse("STRASSE");
		adr2.setPlz("PLZ");
		adr2.setOrt("ORT");
		adr2.setLand(laender.getListLaender().get(1));
		
		Telefon t = MitgliederFactory.eINSTANCE.createTelefon();
		t.setArt(Telefonarten.MOBIL);
		t.setNummer("123123");
		t.setVorwahl(laender.getListLaender().get(0));
				
		Mitglied m = MitgliederFactory.eINSTANCE.createMitglied();
		m.setAnrede(Anrede.HERR);
		m.setVorname("1");
		m.setNachname("2");
		try {
			m.setGeburtsdatum(sdf.parse("01.01.1900"));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		m.setStaatsbuergerschaft(laender.getListLaender().get(0));
		m.getAdressen().add(adr);
		m.getTelefonnummern().add(t);
		
		mitglieder.getListMitglieder().add(m);

		Mitglied m2 = MitgliederFactory.eINSTANCE.createMitglied();
		m2.setAnrede(Anrede.FRAU);
		m2.setVorname("1");
		m2.setNachname("2");
		try {
			m2.setGeburtsdatum(sdf.parse("01.01.1900"));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		m2.setStaatsbuergerschaft(laender.getListLaender().get(1));
		m2.getAdressen().add(adr);
		m2.getAdressen().add(adr2);
		
		Partner p = MitgliederFactory.eINSTANCE.createPartner();
		p.setAnrede(Anrede.FRAU);
		p.setVorname("1");
		p.setNachname("2");
		p.setStaatsbuergerschaft(laender.getListLaender().get(1));
		m.setPartner(p);
		
		mitglieder.getListMitglieder().add(m2);
	}
	
	public Mitglieder getMitglieder() {
		return mitglieder;
	}
	
	public Laender getLaender() {
		return laender;
	}
}
Zugreifen tu ich dann immer über 'Laender laender = ModelProvider.INSTANCE.getLaender();'...
Ist das Sinnvoll oder Blödsinn, weil ich irgendwie direkt auf das EMF zugreifen könnte?

So, das wärs mal fürs erste, kann gern noch mehr Code liefern, falls gewünscht.

Würde mich auf jeden Fall sehr über Antworten freuen,
bis dahin noch schönes WE & lg
O
 
Das über den Command Stack laufen zu lassen ist denkbar einfach. Statt EMFProperties verwendest du EMFEditProperties und übergibst die Editing Domain, der Rest bleibt identisch.
Für die Länder könntest du ein Enum verwenden wenn ich dich richtig verstanden habe.
 
Danke Wildcard für den Hinweis, prob ist auch, woher ich das EditDomain bekomme... kann ich das nur erzeugen, wenn ich mein Modell in einem XMI File ablege, oder geht das ganze auch, wenn mein Modell nur im Speicher liegt?

danke und lg
 
Danke Wildcard für den Hinweis, prob ist auch, woher ich das EditDomain bekomme... kann ich das nur erzeugen, wenn ich mein Modell in einem XMI File ablege, oder geht das ganze auch, wenn mein Modell nur im Speicher liegt?
Nein, mit XMI hat das nichts zu tun. Die Editing Domain ist der Zugang zum Command Stack. Alle Editoren und Views die auf der gleichen Modell Instanz operieren, sollten sich die gleiche Editing Domain Teilen.
Der generierte Editor erzeugt zB eine Editing Domain und stellt sie der generierten Properties View zur Verfügung.
 
Hi Wildcard,

danke für deinen Tipp!
habs jetzt mit deiner (und Sir Wayne's :) ) Hilfe hinbekommen (dieser Thread)...Ich definiere also ein EditingDomain, verwende beim Binding die EMFEditProperty und kann über den BasicCommandStack undos und redos ausführen... so weit so gut :)

Jetzt wäre meine Frage: kann ich quasi ganze Bearbeitungen nur im Stack ablaufen lassen, ohne dass sie im Modell zu sehen sind, und dann mehr oder weniger mittels eines SaveAllChanges oder sowas diese übertragen?

atm ists so, dass ich im TableViewer meine Einträge habe, in einer zweiten View bearbeite ich diese. Dort wird alles auf den Commandstack geschrieben (undo/redo funzt), aber es wird wegen des bindigs direkt auch im modell gezeigt (also im TableViewer). Bisher war das wünschenswert, jetzt hätte ich aber lieber, dass die Änderungen erstmal vorgenommen werden, und dann eben durch einen save button gespeichert werden.

Geht das über den CommandStack, oder muss ich dafür statt einer View einen Editor verwenden? bzw ist mir da der unterschied nicht richtig klar... habe nur mehrfach schon den Editor gesehn.

An dieser Stelle nochmal einen herzlichen Dank vA an dich, Wildcard, dass du meinem Programmier-Schmutz immer so geduldig liest und dazu auch antwortest :) echt tolle Sache!

beste grüße!
 
Geht das über den CommandStack, oder muss ich dafür statt einer View einen Editor verwenden? bzw ist mir da der unterschied nicht richtig klar... habe nur mehrfach schon den Editor gesehn.
Der Command Stack ist der falsche Ansatzpunkt. Dort werden Commands abgelegt die das Modell manipuliert haben, um diese Änderungen Rückwärts wieder abzuspielen. Der wichtige Punkt is: das Modell wurde bereits verändert.
Eine Möglichkeit wäre zB das du in einer View auf einer Kopie der original Modells arbeitest, damit du 2 verschiedene Instanzen hast. Das geht sehr einfach mit EcoreUtil#copy.
Die View hat dann ihren eigenen Command Stack und ihre eigene EditingDomain. Bei 'save' wendest du dann alle Commands aus dem Stack der View auf das orignal Modell an.
Ist in jedem Fall komplizierter als ein Live Edit.
Gibt es bestimmte Gründe warum du das so haben willst? In Eclipse werden die Änderung in der Properties View zB auch direkt übernommen und der entsprechende Editor wird dadurch 'dirty'.
Dann liegt es am Nutzer ob er den Editor speichern will, oder nicht.
 
Hey,

erstmal danke für den Input.

Mein Gedanke war es, Bearbeitungen entweder direkt (so wie von dir beschrieben und über den CommandStack) zuzulassen, oder sie über einen Dialog zu leiten, wo die Daten in übersichtlicherer Form bearbeitet werden können. Allerdings hat natürlich der Dialog die Abbrechen-Möglichkeit, und ich dachte bisher fälschlicherweise, dass mir der Commandstack quasi erlauben würde, alle Änderungen zu verwerfen. Oder anders gesagt dachte ich , dass durch das EditingDomain das ganze Bearbeiten eigentlich über eine eigene Instanz laufen würde, welche dann quasi committed oder eben verworfen werden müsste. Anscheinend war der Gedanke falsch :)

Wie würde in dem von dir beschrieben Fall gespeichert werden, wenn der ganze Editor dirty ist? Zumal ich - soweit ich das verstanden habe - nicht in einem Editor, sondern in einer View arbeite... ist das ein Problem/Design-/Denkfehler von mir, den ich besser ausbessern sollte? Oder bin ich schon wieder am Holzweg?

Danke für deine Geduldigen Erklärungen :D

Gute Nacht und lg
 
Das normale Pattern ist: Editor bearbeitet eine Datei, View unterstützt. Der Editor hat eine Instanz des Modells (initial aus Datei geladen). Die View bearbeitet das Modell, der Editor wird dirty. Wenn nun der Editor gespeichert wird, serialisiert der Editor das Modell in die Datei.
 
Hi,

dh ich sollte mal von "alles im view machen" hin zu "editor und view" gehen? Werd ich mir mal ansehen, danke!

Ist der MasterDetailBlock hier das Mittel der Wahl?

danke und lg
 
Wie gesagt, das übliche Paradigma ist: Editor editiert und View unterstützt. Da ich aber deine Anwendung nicht kenne will ich dir nicht sagen was für dich besser oder schlechter passt.
 
Ah, ok, danke, habs anfangs nicht ganz gerafft!

kurze Erläuterung mein Programm: stinknormale Adressverwaltung (Klassen: Personen mit Adressen & Kontaktnummern) diese hab ich bisher in eine Enum (INSTANCE) "geladen" (Persistierung gibt es noch nicht, daher dort erzeugt).

Habe dann 2 Views erzeugt, eine fungierte als "Master" (TableViewer, welche eine getPersonen() aus der Enum als Input abgerufen hat) und die Zweite war "Detail", also gebundene Felder zum Bearbeiten der Masterselektion.

Fragen dazu:
-Wird ein Editor gesondert auf der UI dargestellt? Oder is der übergeordnet, enthält eine (mehrere?) Views und verwaltet diese?
-Kann ich mein EMF Modell direkt an einen Editor binden?
-Ist dieser MasterDetailBlock (org.eclipse.ui.forms) Teil dieses Editor/Viewer Paradigmas oder ist das eine eigene Implementierung davon (evtl. nicht an ein EMF Modell bindbar?)

DANKE wieder für deinen tollen Input, das Bild in meinem Kopf nimmt immer mehr Umrisse an (Details und Farben fehlen noch, aber ich bin ja noch jung :) )

Liebe Grüße!
 
G

Gast2

Von einer View gibt es meistens nur eine Instanz von einem Editor kann es mehrere Instanzen geben die jedesmal IEditorInput entgegen nehmen.
Eclipse RCP Tutorial

EMF hat ein eigenes Databinding, welches du an widget hängen kannst ähnlich wie das JFaceBinding

Hier ein Beispiel das Undo/Redo unerstützt

Java:
EMFDatabindingContext bindingContext;
IEMFEditValueProperty prop = EMFEditProperties.value(editingDomain,
				eStructuralFeature)
bindingContext.bindValue(
				SWTObservables.observeDelayedValue(bindDelay,
						SWTObservables.observeText(textfield.getTextControl(), SWT.Modify)),
				prop.observe(eObject));
Dein Editor oder view braucht dann noch EditingDomain für undo/redo und muss IEditingDomainProvider implementieren
Java:
	protected void initializeEditingDomain() {
		// Create an adapter factory that yields item providers.
		ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(
				ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
		// Create the command stack that will notify this editor as commands are
		// executed.
		BasicCommandStack commandStack = new BasicCommandStack();
		commandStack.addCommandStackListener(new CommandStackListener() {

			@Override
			public void commandStackChanged(EventObject event) {
				fireDirtyPropertyChange();
			}
		});
		editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack, new HashMap<Resource, Boolean>());
	}
 
-Wird ein Editor gesondert auf der UI dargestellt? Oder is der übergeordnet, enthält eine (mehrere?) Views und verwaltet diese?
Wenn du Eclipse verwendest, weißt du bereits wie Views und Editoren arbeiten. Der Java Editor ist ein Editor, die Outline eine View die den Editor unterstützt.
-Kann ich mein EMF Modell direkt an einen Editor binden?
Für das Modell ist egal ob es in einem Editor, View, oder beidem angezeigt wird.
-Ist dieser MasterDetailBlock (org.eclipse.ui.forms) Teil dieses Editor/Viewer Paradigmas oder ist das eine eigene Implementierung davon (evtl. nicht an ein EMF Modell bindbar?)
Ein MasterDetailBlock ist üblicherweise in einem Editor zu finden. Der Editor für die Plugin.xml enthält einen solchen Block. Der Tree/die Liste links ist Master, je nach selektion bekommst du dann rechts davon andere Optionen (Details)
 
Danke für die Anregungen, bin am Wochenende nicht dazu gekommen, den editor mal neu zu schreiben! Werds aber in den nächste Tagen machen, und mich dann nochmals melden!

thx und lg
Markus
 
Hi Leute,

danke, hab mich mal am Editor versucht, diesen aber dann verworfen, weil er verdammt kompliziert wer und mmn. recht viel Code dabei hatte, den ich eigentlich nicht brauche.

Mir ist aber jetzt ein anderes Problem aufgefallen, welches ich noch nicht gelöst habe (wenn Ihr wollt mach ich dafür gern einen neuen Thread auf):

-Mein Modell hat die Klasse Person, welche beliebig viele Adressen (Klasse Adresse) halten kann. diese werden als Verweis listAdressen gehalten.
Ich stelle dies dar, indem ich die Adressen in einem ListViewer ausgebe, und zwar wie folgt:
Java:
lvAdressen.setContentProvider(new ObservableListContentProvider());
WritableList input = new WritableList(aktPerson.getAdressen(), Adresse.class);
lvAdressen.setInput(input);
Das Problem ist jetzt, dass sich die Liste nicht automatisch aktualisiert, wenn ich über einen Button ein neues Adressenobjekt anhänge. erst mit
Code:
 lvAdressen.refresh();
wird mir das neue Objekt angezeigt. Das liegt wohl daran, dass ich mein Personenobjekt nicht direkt an den ListViewer gebunden habe.... nur: wie bewerkstellige ich das? Hab im Zusammenhang mit TableViewer öfters das ViewerSupport.bind() gesehen, dies aber nicht auf meinen ListViewer umlegen können... hat da jemand ein Beispiel oder einen Tipp dazu?

[EDIT]
Hab das selbe Problem auch eine Ebene darunter: meine TableViewer, welcher alle Personenobjekte hält, aktualisiert den Eintrag zur Adressensammlung nicht... erst auf Refresh.
Java:
ObservableListContentProvider obsListCP = new ObservableListContentProvider();
tableViewer.setContentProvider(obsListCP);

IObservableMap[] obsMap = EMFObservables.observeMaps(obsListCP.getKnownElements(), new EStructuralFeature[] { Literals.PERSON__ANREDE, Literals.PERSON__VORNAME, Literals.PERSON__NACHNAME, Literals.PERSON__GEBURTSDATUM, Literals.PERSON__STAATSBUERGERSCHAFT, Literals.PERSON__ADRESSEN, Literals.MITGLIED__PARTNER, Literals.PERSON__EMAIL });
tableViewer.setLabelProvider(new ObservableMapLabelProvider(obsMap));

IObservableList mglObsList = EMFObservables.observeList(Realm.getDefault(), mitglieder, Literals.MITGLIEDER__LIST_MITGLIEDER);
tableViewer.setInput(mglObsList);
Die Ausgabe erfolgt mithilfe eines modifizierten ColumnLabelProvider, der die erste Adresse ausgibt und weitere mit [+x] angibt. Funktioniert, allerdings werden Änderungen am ersten Adressobjekt erst nach refresh sichtbar. Wenn ich allerdings lösche, wird das erste Objekt sofort entfernt und das 2te rückt automatisch nach... nur warum ???:L :rtfm:

[/EDIT]

Vielen Dank und LG!
 
Zuletzt bearbeitet:
G

Gast2

Du brauchst kein Databinding für eine Tabelle bzw. Tree benutz einfach die richtigen Adapter die dir EMF mitgeneriert...

für eine tabelle mit einer person, die mehrere adressen hat.
Java:
	AdapterFactory adapterFactory = new MyProviderAdapterFactory();
		viewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory));
		viewer.setContentProvider(new AdapterFactoryContentProvider(adapterFactory));
		viewer.setInput(person);
 
Danke,

leider wird mir dann nichts angezeigt... muss ich da rundherum noch mehr machen?

zudem frag ich mich, wie er wissen soll, dass ich aus der Sammlung Person nur die Adressen will, und nicht zB. Vor/Nachname...

Kann ich zudem da Felder irgendwie anpassen, so wie ichs bisher über die gesonderten Labelprovider der Columns gemacht habe?

Sorry, dass ich mit sovielen gegenfragen daher komm... bin leider etwas planlos :)

lg!
 
Danke Sir!

deine Beiträge haben mir schon viel geholfen ;) Haben anscheinend viele am Anfang ähnliche Probleme ...

Besten dank und lg :)
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben