As Sergiu mentioned on one of his previous posts, we are working on a quite large project, a very specific ERP, where we have decided to use Prism as composition framework.
Studying Prism we've learned a lot on how composite applications should be built, on how we should modularize our application and how to make things uncoupled as much as possible. From the begging we've felt that if we manage to apply these concepts, knowing that we are facing a quite big project with a very ambitions deadline and with a quite large team of developers, we will benefit both on development efficiency and later, on maintainability and extensibility. So, Prism seamed the best choice even if it was built for WPF and Silverlight and we were in Windows Forms world.
We knew that we will have to adapt a few concepts to Windows Forms. Looking on how Prism is built, everything abstracted in interfaces we had the feeling that it is possible. I mean, nobody stops you to change the implementation of a few interfaces. After studying it some more, and reading Brian Noyes blog we knew it was possible, so with a lot of enthusiasm we started to get into it.
Regions and RegionManager were some of the concepts we had to implement from scratch. I will detail our implementation for them and how we got to it.
I would like to mention, from the beginning that our approach in entire project is to do things step by step, to start with small prototype solutions, which later, while we are getting more experience, to be grown and improved by subsequent refactoring iterations. So, even if now, our implementation of Region and RegionManger works and responds to all needs in our project, I am sure that it didn't reach its maturity. It can be generalized more and there are more improvements that can be done.
We've tried to keep as close as possible to Prism's concept of Region and RegionManager. Because some concepts from WFP differ a lot from Windows Forms, for instance in WFP the UI composition is native, we did not entirely kept the interfaces from Prism. We extended them. One reason for trying not to derive too much from Prism was that we wanted to be able to easily migrate our extensions to next versions of Prism when it will be the case.
Starting from UI Composition concept in Prism, we have the Shell window. We always had in mind some common applications we use, as examples, like Outlook or VisualStudio. So, on our Shell we've needed a MainRegion which will have more windows (tabbed or not) similar with the code window from VisualStudio. We've also needed a navigation view, which we've put on a docking panel, so we have a DockPanelRegion for all docking views that we'll need. Beside the Shell we also needed to have other windows. We've needed non-modal windows, so we have a PopupRegion and we've needed modal dialogs, so we have DialogRegion. We've also foresaw that we would have toolbars specific to a certain module modeled as views, like in VisualStudio, so we've added ToolbarRegion in the Shell too.
Having these in mind and with the fact that in every module we'll have implementations of Model-View-Presenter pattern, we wanted to achieve that any presenter can say: "Add this view to that region and activate it". So we've started to assign responsibilities. Clearly the RegionManager will manage all these regions. Then each region will have more views and some of them will be active. It is each region's responsibility to visually present active and inactive views. For instance in MainRegion where there are tabbed window views (again VisualStudio code windows example) there is only one active view at a moment. The other ones are hidden and only their tab caption is visible, so the user can activate them. If the user changes this from tabbed windows to MDI cascaded windows then again it is region's responsibility to implement that. This differs from region to region. For instance in DockPanelRegion there may be more views active at same moment. All these are implemented in specific classes for each region.
We may have same view type in different regions, so we needed a way to adapt any view to any region. For this we added ViewHost. This is specific to a region type. It adapts any view to the region's specific. For MainRegion it is, in fact, a Form which can be added to MainRegion tabbed windows controls, for DialogRegion is a Form shown in modal mode and for DockPanelRegion is a panel which can be added to the docking control. The ViewHost also notifies the view it hosts about activation events. Because we didn't want to go far from Prism implementation, the region holds a collection of views, not of view hosts and when a view instance is hosted (adapted to a region), it holds a reference to its host.
The diagram bellow shows an overview:

To keep a clear separation from our application specifics to the extensions we did to Prism we have adopted the regions identification by name. In application's Bootstraper we register in RegionManager, IRegion implementations by name. So, IRegion is part of Prism's extensions, but its implementations are application specific. When any presenter needs a region, to add or open a view, it will ask an IRegion from RegionManager by its name.
So, we have Shell's regions, plus pop-ups and dialog regions. What misses is view composition. In Windows Froms is quite common to place a user control, with logic and all, inside another user control. In our case this means that we need a view inside another view. Imagine a wizard. In each step we want views that were used in other parts of the application and they are linked by the logic in the wizard presenter. Each view is controlled by its own presenter, and each one shows data from other models. They even may be from different modules. How to accommodate this, taking into account Model-View-Presenter and Regions? What we did was to create so called ViewContainer, which is a generic user control that is a IViewHost. This ViewContainer can adapt any view. The developer when he creates a view, he can drag from Toolbox, in VisualStudio designer, a ViewContainer. He can adjust its sizes and all. Now the presenter should be able to add its view to this ViewContainer. To keep the consistency that a presenter adds views to a region we have created a ViewContainerRegion which receives the ViewContainer and uses it as a view host to adapt the view. So, the presenter will instantiate a ViewContainerRegion (it no longer asks for the region from the RegionManager) and then it adds and activates its view in this region and it's all done.
With this implementation we managed to accommodate Windows Forms and Prism. The result, so far, is that it provides all needed infrastructure for UI Composition that our application needs and for developers is easy to comprehend and use. In fact from outside you just need to know the name of the region you want to put your view in. Then you ask for the RegionManger instance and you say to it: "Put my view in the region with this name" J quite easy.
As I was saying at the beginning I am sure that this can be taken much further. One of the improvements that come to my mind now, is to have more views in a ViewContainerRegion by having them in different forms (tabbed, one visible, all visible etc.). This would mean to generalize this type of region and to have the developer to drag on his view the region not the view host. Another improvement which can be done is to have more composite windows as mini-Shells, each one with its own regions and RegionManager. Until now, our implementation only has one RegionManager instance, unlike it is in Prism. So, it is always place for improvements and refactories ...