Yuval, via a comment, asks:

Can you explain why you chose to define WrapperElement<T> instead of simply inheriting from Decorator? They seem to be doing the same thing.

Ah, it is good to read my post "Don't subclass a Panel, unless you're making a Panel".

First, where do I used WrapperElement<T>? Well, at the moment, it's used in three places: FlipTile3D, Set, and Transition3D. In all cases it simply wraps a Viewport3D.

Now, could I simply use Decorator? Sure. I could subclass Decorator and do basically the same thing. Even easier: I could subclass Viewport3D.

Why don't I?

It's all about API usability and correctness.

When I write a control (especially for the bag-o-tricks) I try to make it "right".

If these controls subclassed Viewport3D, they should act like Viewport3D. Meaning, they should support someone added arbitrary lights, models, etc. They should support messing with and removing elements that are already added.

I don't want this.

Wrapping everything with a Decorator, just exchanges problems.

If I subclass Decorator, it would imply that I mean people to treat the control like a Decorator, which means accessing and changing the Child property.

I don't want this, either.

WrapperElement<T> does some very simple things.

  • Stores a Framework element as a child visual.
  • Adds it to its visual tree (via AddVisualChild)
  • overrides GetVisualChildCount
  • overrides VisualChildCount
  • overrides MeasureOverride
  • overrides ArrangeOverride
  • Provides protected access to the child so the subclass can play with it, but not the end user.

One should use WrapperElement<T> when one wants to use the implementation of an existing component--Viewport3D, Grid, etc.--but doesn't want the object model of that component exposed.

Make sense?

Thanks for the question, Yuval.

Happy hacking.