As @fabian mentioned correctly, the size of a VBox is entirely dependent the sizes of its children. If you wish to have a container that does not resize depending on its children, you can use a Pane instead. Like this:
public void start(Stage primaryStage)
{
GridPane root = new GridPane();
Scene scene = new Scene(root, 300, 300);
int c = 0, r = 0;
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
root.add(c0, c, r);
primaryStage.setScene(scene);
primaryStage.show();
}

Add a shape to test:
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
{
Circle circle = new Circle(160, Color.BLUE);
circle.setCenterX(160);
circle.setCenterY(160);
c0.getChildren().add(circle);
}
root.add(c0, c, r);

Note that although the shape protrudes outside of the bounds of c0, the borders of c0 stay in place, indicating that its size is unaffected. To prevent the content from protruding out, you need to add a clip:
c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));

If you want a more fancy clip instead of a simple trim, such as fade-in, fade-out, and shadows, you can read this very good tutorial here.
Now just replace this Circle with your VBox, so that the VBox is a child of this Pane, and add the Pane to your GridPane and you're done. I will provide my final code here as a reference:
public void start(Stage primaryStage)
{
GridPane root = new GridPane();
Scene scene = new Scene(root, 300, 300);
int c = 0, r = 0;
Pane c0 = new Pane();
c0.setPrefSize(200, 200);
c0.setClip(new Rectangle(c0.getPrefWidth(), c0.getPrefHeight()));
c0.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
new BorderWidths(1))));
{
Circle circle = new Circle(160, Color.BLUE);
circle.setCenterX(160);
circle.setCenterY(160);
c0.getChildren().add(circle);
}
root.add(c0, c, r);
primaryStage.setScene(scene);
primaryStage.show();
}
Update:
@Jai pointed out that the size is static in this implementation. If you wish to dynamically adjust the size of the cells if the size of the GridPane changes, you can add a listener to its widthProperty and heightProperty like this:
int rowCount = 5, columnCount = 7; // You should know these values.
ChangeListener<Number> updater = (o, oV, nV) ->
{
double newWidth = root.getWidth() / columnCount;
double newHeight = root.getHeight() / rowCount;
root.getChildren().forEach(n ->
{
// Assuming every child is a Pane.
Pane p = (Pane) n;
p.setPrefSize(newWidth, newHeight);
p.setClip(new Rectangle(newWidth, newHeight));
});
};
root.widthProperty().addListener(updater);
root.heightProperty().addListener(updater);
Alternatively...
If you wish to use ColumnConstraints and RowConstraints to determine the cell size you can set the Panes to expand, and only update their clips in the listener, which now listens to ColumnConstraints and RowConstraints:
ColumnConstraints cc = new ColumnConstraints(200);
RowConstraints rc = new RowConstraints(200);
c0.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
c0.setClip(new Rectangle(cc.getPrefWidth(), rc.getPrefHeight()));
and...
ChangeListener<Number> updater = (o, oV, nV) ->
{
root.getChildren().forEach(n ->
{
// Assuming every child is a Pane.
Pane p = (Pane) n;
p.setClip(new Rectangle(cc.getPrefWidth(), rc.getPrefHeight()));
});
};
cc.prefWidthProperty().addListener(updater);
rc.prefHeightProperty().addListener(updater);