Congratulations--you've found a genuine "undocumented feature" in CAB. It took Ward and myself quite a while to figure it out.
It turns out that when a view is being built (a consequence of ViewFactory.AddNew<>(), the object builder traverses the view's control hierarchy and adds certain controls to the Items collection of the workitem. These are:
SmartParts (doesn't happen often because we rarely add SmartParts statically to a view),
These are added to the workitem Items collection using a key value composed of
1. The value of the control's Name property
2. The name of the control's type.
If the control's Name property is null, a GUID is used instead.
When the first ThreePanelView is created, its SmartPartPlaceholders are added to the items collection using the names mLeftSmartPartPlaceholder, etc. When the second ThreePanelView is created, it attempts to add the same three names and throws the exception. This will happen any time we try to add two instances of a view that contains any of the above three control types.
So, the workaround is to give the SmartPartPlaceholders unique (or null) names. This can be done in ThreePanelView in the PresenterReady() method:
/// Configure the view once the Presenter declares it is ready.
protected override void PresenterReady(EventArgs e)
// Set the SmartPartPlaceholder names to null so they will be
// added to the workitem's Items collection with unique (GUID) names
mLeftSmartPartPlaceholder.Name = null;
mMiddleSmartPartPlaceholder.Name = null;
mRightSmartPartPlaceholder.Name = null;
// Assign the view ids to be displayed in the SmartPartPlaceholders
mLeftSmartPartPlaceholder.SmartPartName = ThreePanelViewContext.LeftViewId;
mMiddleSmartPartPlaceholder.SmartPartName = ThreePanelViewContext.MiddleViewId;
mRightSmartPartPlaceholder.SmartPartName = ThreePanelViewContext.RightViewId;
Alternatively, we could use:
mLeftSmartPartPlaceholder.Name = ThreePanelViewContext.LeftViewId+"SPH";
mMiddleSmartPartPlaceholder.Name = ThreePanelViewContext.MiddleViewId+"SPH";
mRightSmartPartPlaceholder.Name = ThreePanelViewContext.RightViewId+"SPH";
Note that we can't create unique names (within the workitem) until the instance of the view is created. Also the designer won't allow setting of null control names.
This should get you back on the air.
Bill & Ward