RegionContext Usage

Topics: Prism v2 - WPF 3.5
Aug 4, 2009 at 10:10 PM

I've posted a question on StackOverflow and I thought I would duplicate it here, since this is a more specific forum for Prism.
http://stackoverflow.com/questions/1228674/share-context-data-with-all-children-of-a-control

Basically I want to have a piece of data that all child controls (all the way down the control tree) can access.  I assumed RegionContext would provide this functionality, but it doesn't.

Any suggestions would be helpful! 

Aug 4, 2009 at 10:58 PM

What about something like the following in your child control constructor?  Where IMyControlPresentationModel (aka ViewModel) was registered in the parent.  This way you can simply bind to the shared model.

myChildControl.DataContext = Container.Resolve<IMyControlPresentationModel>();

 

Aug 5, 2009 at 3:55 AM

Yeah... that's something we are kicking around and is our top contender.  This also has the advantage of putting the data where it belongs: in the view model.  The rub here is that each view I add will have a different set of data, so that will require a scoped unity container per item that gets thrown in that Region.  Not a big deal, but it seems like sort of an abuse of the container, but maybe not.  Is putting a Model object in the container "wrong"?  

Feels wrong somehow, but no more wrong than relying on the UI to route data to the ViewModel, I suppose.

Aug 5, 2009 at 5:05 AM
Edited Aug 5, 2009 at 5:09 AM

Hi andersonies,

I use the DI container to loosely  couple - so within that context it shouldn't feel wrong.   For example, I have a Multi-Targeting application (http://multitargeting.codeplex.com/ should be activated within a few days) that has a series of PrismContrib.xxxxx projects where xxxx = WPFWinForms and Silverlight (Silverlight is shared by regular Silverlight as well as RIA Services) - so I essentially have four separate platforms sharing the same codebase (transparent to the developer). 

Setting up a module will be as simple as setting references as applicable and then complying with the Model-View-Presenter pattern, coupled with the PresentationModel (aka Model-View-ViewModel).   e.g., the following is the most complicated work that will have to be done - setting up the presenter with the applicable View interface (derived from IView) and PresentationModel interface (derived from IPresentationModel).  

 

namespace Module.Client.Views.Details
{
    public class DetailsViewPresenter : PresenterBase<IDetailsView>
    {
        public DetailsViewPresenter(
            IDetailsView view, 
            IDemoPresentationModel model, 
            IUnityContainer container) : base(view, model, container)
        {

        }
    }
}

Using P&P learned while working with the Smart Client Software Factory  I let PresenterBase do the wiring up.  I have special processing so that the behaviors for all platforms are consistent.   All of my Views (UserControls) use this so for me wiring up the data context is a mute point.  The Modules registering types as applicable for that module.  

This permits me to use a single framework (PRISM and PrismContrib.xxxxx) for multiple applications while remaining loosely coupled.   In MVP tightly coupling the View to the Presenter (and visa versa) is not an issue because it is a one-to-one relationship.   The PresentationModel on the other hand can be shared by multiple views (doesn't have to be) so we let the Presenters carry the responsibility of populating the PresentationModel(s).

For your reference the PresenterBase code follows:

public PresenterBase(IView view, IPresentationModel model, IUnityContainer container)
{
    try
    {
        // For logging purposes
        ModuleName = GetType().FullName;

        // Setter injection is not available until after the constructor
        // so we'll set them manually
        Error = container.Resolve<IError>();
        Logger = container.Resolve<ILoggerFacade>();

        // Set the presenter with a reference to the container
        Container = container;

        // Set the Presenter with a reference to the model
        Model = model;

        if ((TView)view is UserControl)
        {
#if !WinForm      
            // WPF/Silverlight have SizeChanged event
            // Provide means to notify User Controls that their size has been set
            ((TView)view).SizeChanged += (object sender, SizeChangedEventArgs e) =>
                {
                    OnViewSizeSet(sender, e);
                };
#endif
        }


        // Set the Presenter with a reference to the view
        View = (TView)view;

        // Subscribe to all Button Click events.  The main view  will bubble
        // all button click events (see MainView code-behind)
     
 container.Resolve<IEventAggregator>()
            .GetEvent<ClickEvent>().Subscribe(OnButtonClickEventHandler, true);

        // Subscribe to any Data Access Layer event changes
        container.Resolve<IEventAggregator>()
            .GetEvent<DALEvent>().Subscribe(OnDALEventHandler, true);

        // Process controls on view
        IControlProcessor controlProcessor = container.Resolve<IControlProcessor>();
        controlProcessor.ProcessControlCollection(View);

        // Set Unity container in View - this will allow us
        // to gain access to the container if all we have is
        // a reference to the view
        View.Container = container;

        // For the XAML forms (WPF and Silverlight) this sets the databinding
        // to the Presentation Model / View Model
        View.DataContext = model;

    }
    catch (Exception ex)
    {
        Error.SetError(ex);  
    }
}