diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings
index 86b47393dc290e086696323a5f07d0be07adb0bb..0cf1dac697e971d2c67647128a92cd5dc8451b10 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings
@@ -1 +1 @@
-AF3FXViewPart.java 9e119a36de6ab9e1a07cd416de0126a89514bd38 GREEN
+AF3FXViewPart.java 96871186e27ace44069441dbf7ac8ebcd7753390 GREEN
diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java
index 9e119a36de6ab9e1a07cd416de0126a89514bd38..96871186e27ace44069441dbf7ac8ebcd7753390 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java
@@ -16,17 +16,21 @@
 package org.fortiss.tooling.common.ui.javafx;
 
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URL;
 
 import javafx.application.Platform;
 import javafx.fxml.FXMLLoader;
+import javafx.scene.Node;
 import javafx.scene.Scene;
+import javafx.scene.layout.AnchorPane;
 import javafx.scene.layout.Pane;
 
 import org.apache.commons.lang3.SystemUtils;
 import org.eclipse.fx.ui.workbench3.FXViewPart;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
 
 /**
  * Base class to create eclipse (SWT-based) views using JavaFX GUI elements. This class requires
@@ -54,48 +58,49 @@ public abstract class AF3FXViewPart extends FXViewPart { // NO_UCD
 	/** References the stub that defines the FXML file defining the layout and controller. */
 	private Class<? extends AF3FXViewPart> viewerClass;
 
+	/** References the root {@link Pane} to which GUI elements must be added to be displayed. */
+	private Pane root;
+
 	/**
-	 * Constructor. Allows to pass the view's FXML definition file along with style.
+	 * Constructor that is intended for {@link ViewPart}s which host a single view/node/control.
 	 * 
 	 * @param viewerClass
-	 *            Stub class that defines the FXML file defining the layout and controller
-	 * @param fXMLLocation
-	 *            location of the fXML file relative to the source (resource) folders.
+	 *            Class implementing the {@link AF3FXViewPart} to load resources from its containing
+	 *            bundle.
+	 * @param cssLocation
+	 *            style sheet file path for the appearance settings relative to the source
+	 *            (resource) folders. Pass {@code null} if the OS-native look shall be used.
 	 * @throws Exception
 	 *             if the given FXML file path is not given or if it cannot be found in any of the
 	 *             source (resource) folders.
 	 */
-	public AF3FXViewPart(Class<? extends AF3FXViewPart> viewerClass, String fXMLLocation)
+	public AF3FXViewPart(Class<? extends AF3FXViewPart> viewerClass, String cssLocation)
 			throws Exception {
-		if(fXMLLocation == null) {
-			throw new Exception(
-					"The location of the FXML file defining the gui elements was not given," +
-							"or it cannot be found at the given location (" + fXMLLocation + ") " +
-							"The view will NOT be created.");
-		}
-
-		Platform.setImplicitExit(false);
-		this.viewerClass = viewerClass;
-		this.fXMLLocation = fXMLLocation;
+		// Initializing the base constructor with "null" for the FXML file indicates a
+		// single-view/node/control usecase.
+		this(viewerClass, null, cssLocation);
 	}
 
 	/**
 	 * Constructor. Allows to pass the view's FXML definition file.
 	 * 
 	 * @param viewerClass
-	 *            Stub class that defines the FXML file defining the layout and controller
+	 *            Class implementing the {@link AF3FXViewPart} to load resources from its containing
+	 *            bundle.
 	 * @param fXMLLocation
 	 *            location of the fXML file relative to the source (resource) folders.
 	 * @param cssLocation
 	 *            style sheet file path for the appearance settings relative to the source
-	 *            (resource) folders.
+	 *            (resource) folders. Pass {@code null} if the OS-native look shall be used.
 	 * @throws Exception
 	 *             if the given FXML file path is not given or if it cannot be found in any of the
 	 *             source (resource) folders.
 	 */
 	public AF3FXViewPart(Class<? extends AF3FXViewPart> viewerClass, String fXMLLocation,
 			String cssLocation) throws Exception {
-		this(viewerClass, fXMLLocation);
+		Platform.setImplicitExit(false);
+		this.viewerClass = viewerClass;
+		this.fXMLLocation = fXMLLocation;
 		this.cssLocation = cssLocation;
 	}
 
@@ -118,14 +123,28 @@ public abstract class AF3FXViewPart extends FXViewPart { // NO_UCD
 	/** {@inheritDoc} */
 	@Override
 	protected Scene createFxScene() {
-		Pane root = null;
 		FXMLLoader loader = new FXMLLoader();
 		loader.setClassLoader(viewerClass.getClassLoader());
-		loader.setLocation(viewerClass.getResource(fXMLLocation));
-		try {
-			root = (Pane)loader.load();
-		} catch(IOException e) {
-			throw new RuntimeException("Cannot load the resource located at " + fXMLLocation, e);
+		if(fXMLLocation != null) {
+			loader.setLocation(viewerClass.getResource(fXMLLocation));
+			try {
+				root = (Pane)loader.load();
+			} catch(IOException e) {
+				throw new RuntimeException("Cannot load the resource located at " + fXMLLocation, e);
+			}
+		} else {
+			root = new AnchorPane();
+			try {
+				viewerClass.getMethod("initialize").invoke(this);
+			} catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException |
+					SecurityException e) {
+				throw new RuntimeException("The initialize method of the View " +
+						viewerClass.getSimpleName() + " threw an exception!", e);
+			} catch(NoSuchMethodException e) {
+				throw new RuntimeException("For single Controller views, an initialize method is "
+						+ "required that creates the control! This cannot be done in constructors "
+						+ "since the JavaFX toolkit is not initialized in that stage.", e);
+			}
 		}
 
 		if(cssLocation != null) {
@@ -134,6 +153,7 @@ public abstract class AF3FXViewPart extends FXViewPart { // NO_UCD
 		if(!isCustomStyleSheetApplied) {
 			setNativeLook(root);
 		}
+
 		Scene scene = new Scene(root);
 		return scene;
 	}
@@ -145,9 +165,50 @@ public abstract class AF3FXViewPart extends FXViewPart { // NO_UCD
 	}
 
 	/**
-	 * Sets the native look of the target platform to break the UI. Most of the UI code is based on
-	 * SWT which uses a platform native look. Currently, Windows 8&10, Windows 7, and MacOS X native
-	 * looks are supported.
+	 * Init method that is called after the JavaFX toolkit has been launched. The initialize method
+	 * is needed for single-node/view/control {@link ViewPart}s and for controls in a FXML-based
+	 * view that require an initial configuration. If no initial configuration is required place a
+	 * stub.
+	 * <p>
+	 * For FXML, the initialize method is called via the JavaFX framework. Otherwise, it is called
+	 * via reflection from this class.
+	 */
+	protected abstract void initialize();
+
+	/**
+	 * Adds a single {@link Node} to this view. It embeds the given {@link Node} to the
+	 * {@link AnchorPane} of this view and stretches it to the borders of the view.
+	 * <p>
+	 * NOTE: This method may only be used for single-control views, not FXML-based ones.
+	 * 
+	 * @param fxNode
+	 *            {@link Node} to be added to the view.
+	 */
+	protected void setChildNodeFinal(Node fxNode) {
+		if(fXMLLocation != null) {
+			throw new RuntimeException("This method is intended for single-control views. It may"
+					+ " not be used for FXML-based views.");
+		}
+		if(!root.getChildren().isEmpty()) {
+			throw new RuntimeException("The method setChildNodeFinal was invoked more than once."
+					+ " This method is intended for single-control views. If more controls"
+					+ "shall be added, please define an FXML layout file and call the appropriate"
+					+ " constructors.");
+		}
+
+		root.getChildren().add(fxNode);
+		// Stretch the node to the borders of the view. In the createScene method, we a create a
+		// root pane that is an AnchorPane, so we can safely use these calls here.
+		AnchorPane.setTopAnchor(fxNode, 0.0);
+		AnchorPane.setRightAnchor(fxNode, 0.0);
+		AnchorPane.setBottomAnchor(fxNode, 0.0);
+		AnchorPane.setLeftAnchor(fxNode, 0.0);
+	}
+
+	/**
+	 * Sets the native look of the target platform to not break the UI experience. Most of the UI
+	 * code is based on SWT which uses a platform native look. Currently, Windows 8&10, Windows 7,
+	 * and MacOS X native looks are supported.
 	 */
 	private void setNativeLook(Pane pane) {
 		if(SystemUtils.IS_OS_WINDOWS_10 || SystemUtils.IS_OS_WINDOWS_8) {
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
index 79965691f84f615b0cba722708810a98539dd0f3..b9c74adc885a96f885f96455338aa033f0bc108b 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/.ratings
@@ -1,5 +1,5 @@
 AutoUndoCommandStack.java 6aa645a9ed6e6547539c376fda97284928c4f9d4 GREEN
 EMFTransactionalCommand.java ba4b5bead9768b6ce6c955b9238cd96cb722533c GREEN
 EclipseResourceStorageService.java 1b9722e31a5ec33e4c3f7bb171fc2ce587729bf8 GREEN
-ModelContext.java 85ede185d4b232221a96d0bf37a4c676b105dc00 GREEN
+ModelContext.java 220944231c0e036f29d4911d2658c33b2427b09f GREEN
 NonDirtyingEMFTransactionalCommand.java ec5f282603891096b09f2628155dd27e3a21c588 GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
index 85ede185d4b232221a96d0bf37a4c676b105dc00..220944231c0e036f29d4911d2658c33b2427b09f 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/internal/storage/eclipse/ModelContext.java
@@ -34,6 +34,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
@@ -151,7 +152,14 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
 			}
 		});
 
-		checkIDs();
+		if(checkIDs()) {
+			try {
+				doSave(new NullProgressMonitor());
+			} catch(IOException | CoreException e) {
+				error(ToolingKernelActivator.getDefault(),
+						"Error saving model file when fixing missing/duplicate IDs.", e);
+			}
+		}
 	}
 
 	/** {@inheritDoc} */
@@ -182,29 +190,35 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
 	}
 
 	/**
-	 * Checks whether all IDs are present and unique and updates {@link #maxId}. In case duplicate
-	 * IDs have been detected (which could only be caused by a bug in AF3), these are removed and an
-	 * error is logged.
+	 * Checks whether all IDs are present and unique and updates {@link #maxId}.
+	 * <ul>
+	 * <li>Duplicate IDs indicate a programming error. They are removed and an error is logged</li>
+	 * <li>Missing IDs are silently added.</li>
+	 * </ul>
+	 * 
+	 * @return {@code true} iff the model was modified because of missing/duplicated IDs (and hence
+	 *         must
+	 *         be saved).
 	 */
-	private void checkIDs() {
+	private boolean checkIDs() {
 		Set<Integer> ids = new HashSet<Integer>();
 
-		boolean hadMissing = false;
-		boolean hadDuplicates = false;
+		// Store String representation of element with duplicated IDs before fixing it
+		Map<String, Integer> objWithIdProblem = new HashMap<String, Integer>();
 		for(Iterator<EObject> i = getRootModelElement().eAllContents(); i.hasNext();) {
 			EObject eo = i.next();
 			if(eo instanceof IIdLabeled) {
 				final IIdLabeled element = (IIdLabeled)eo;
 				int id = element.getId();
 				if(id <= 0) {
-					hadMissing = true;
+					objWithIdProblem.put(element.toString(), null);
 				} else {
 					// Reset duplicate IDs. They will be regenerated together with missing IDs. This
 					// is a safe operation since at this stage, references are still based on Java
 					// references. Only in the persisted resource, references will be based on IDs,
 					// which is why special care must be taken to ensure uniqueness.
 					if(ids.contains(id)) {
-						hadDuplicates = true;
+						objWithIdProblem.put(element.toString(), element.getId());
 						runAsNonDirtyingCommand(() -> {
 							element.setId(0);
 						});
@@ -218,24 +232,31 @@ class ModelContext implements ITopLevelElement, CommandStackListener {
 
 		maxId = max(0, maxId);
 
-		if(hadMissing || hadDuplicates) {
+		if(!objWithIdProblem.isEmpty()) {
 			runAsNonDirtyingCommand(() -> {
 				maxId = generateMissingIDs(getRootModelElement(), maxId);
 			});
-			try {
-				doSave(new NullProgressMonitor());
-			} catch(IOException | CoreException e) {
-				error(ToolingKernelActivator.getDefault(),
-						"Error saving model file when fixing missing/duplicate IDs.", e);
-			}
-		}
 
-		if(hadDuplicates) {
-			String msg = "Duplicate IDs have been removed from \"";
-			msg += resource.getURI().lastSegment() + "\". ";
-			msg += "Please report this incident since it could result in corrupted model files.";
+			String msg = "The following missing/duplicate IDs have been fixed in \"";
+			msg += resource.getURI().lastSegment() + "\".\n";
+			msg += "Please report this incident since it indicates a programming error ";
+			msg += "that could result in corrupted model files.\n";
+			for(Entry<String, Integer> entry : objWithIdProblem.entrySet()) {
+				Integer id = entry.getValue();
+				if(id == null) {
+					msg += "  Missing ID added to ";
+				} else {
+					msg += "  Duplicate ID " + id + " disambiguated for ";
+				}
+				String name = entry.getKey();
+				msg += "element \"" + name + "\"\n";
+			}
 			error(ToolingKernelActivator.getDefault(), msg);
+
+			return true;
 		}
+
+		return false;
 	}
 
 	/** {@inheritDoc} */