Architecture of sub controls in regions

Topics: Prism v1, Prism v2 - Silverlight 2, Prism v2 - WPF 3.5
Mar 27, 2009 at 3:32 PM
Hello,
I could do with some advice on how to go about architecting the following using a module-view(-presenter) architecture using unity and prism.

The main module's purpose is to edit, say a Line. The Bootstrapper initializes a LineModule, which registers a LineView into a region on the Shell called "LineRegion".
Its data will also be stored in and manipulated by a LineModel.

So far so good.

The Line, however, is described by a Start and and End. Now the Start and the End are complex data structures (say, a Point) in themselves and need their own controls for editing them.
So, these want to also conform to the MVP architecture, so I will have a PointModel, and a PointView.
However, I am a bit lost as to how to arrange these with respect to the Line view.

Firstly I am presuming it would be nonsensical to define a PointModule? Since the Point editing functionality is a sub-function of the Line editing functionality...?

The 'holy grail' if you like, would be to have it so that:
* the LineView can define regions called "StartPoint" and "EndPoint", and 
* into each of these will be loaded a PointView, 
* each PointView which will be instantiated by the unity container, thus creating for each one a PointModel automatically which it takes in its constructor
* ... but each PointModel will be able to be referred to by the LineModel!
does that make sense?!
Is this possible?! ;-)

Will any regions I define in the LineView be picked up by the region manager and in what section of code should they be registered with their respective PointView?

Also how would I go about making two PointModel objects available to the LineModel, such that the LineModel can refer to StartPoint and EndPoint individually?
i.e.
public class LineModel : ILineModel
{
    private IPointModel startPoint;
    private IPointModel endPoint;

the important thing is that it needs to refer to each of them, not just have an arbitrary collection of them - so it needs to have a reference to each one.


Thanks for any help, much apprecated


Mar 27, 2009 at 8:42 PM
Edited Mar 27, 2009 at 9:10 PM

Hi,

 

 If I understood you correctly you are having problems on how to create LineModel and PointModel instances in such a way that LineModel can reference to its child startLine and endLine individually.

A thing that I agree with you that it is not necessary to create a PointModule.

 

The way I believe this could be achieved is doing something like the following:

1.       The LineView defines regions called "StartPoint" and "EndPoint"

2.       The LineModel receives in its constructor an instance of a LineView, and two instances of its PointModels.  This way both the LineView and PointModels instances will be created by unity and injected into the LineModel:

    public class LineModel

    {

        private IPointModel startPoint;

        private IPointModel endPoint;

 

        public LineModel(ILineView lineView, IPointModel startPoint, IPointModel endPoint, IRegionManager regionManager)

        {

            this.startPoint = startPoint;

            this.endPoint = endPoint;

            regionManager.Regions["StartPoint"].Add(this.startPoint.View);

            regionManager.Regions["endPoint"].Add(this.endPoint.View);

        }

 

        ...

    }

 

3.       In the PointModel constructor receive an instance of PointView. The PointView instance will created by unity and injected into the PointModel.

 

public class PointModel

     {

        private IPointView view;

        public PointModel (IPointView pointView)

        {

              this.view = pointView;

        }

 

        ...

     }

 

 

Benefits:

·         This way the LineModel will be able to reference each of it's point individually.

·         The line model is testable and you can mock the different point models.

·         Each model creates it's own view.

·         Unity is used to create all instances.

Drawbacks:

·         LineModel has a dependency on the RegionManager. This can be avoided creating a LineController.

·         You are creating a Region for each point. Depending on your scenario it might be a better solution just to databind the each point to the Control you desire without creating a region on it.

 

 

Hope it helps!

 

Matias Bonaventura

http://blogs.southworks.net/matiasb

Mar 30, 2009 at 2:11 PM
Hi,
Thanks for this - it works well.
The only thing I have different to what you have suggested is that instead of the LineModel taking an instance of the LineView in its constructor, I have it the other way round - the LineView takes an instance of the LineModel. The LineModule forces the creation of the LineView, using
regionManager.RegisterViewWithRegion("MainRegion", unityContainer.Resolve<LineView>)
I suppose it could instead be like you said and have
regionManager.RegisterViewWithRegion("MainRegion", () => unityContainer.Resolve<ILineModel>().View)
however, I'm not sure whether is a worse sin - the view knowing about the model or the model knowing about the view?? :-), or should neither cause any particular concern?

And where would a LineController sit in the scheme of things, i.e what (interfaces) would it know about and what would know about it(s interface)?


Mar 30, 2009 at 2:23 PM
ok i've got the LineController working now, that's fine, thanks.
Mar 30, 2009 at 8:22 PM
Edited Mar 30, 2009 at 8:23 PM

Hi,  

Both approaches, having the model be logically created first (know as Presenter-First) and having the view be logically created first(known as View-First), are perfectly valid. In most scenarios the view discovery approach lends itself most naturally to view-first composition. If you are interested in the difference between these approaches you might find useful the UI Composition design concept from the documentation.

 

Regarding the controller, you should think of it as a controller of the whole module, coordinating all necessary view/presenters of the module. You might find this related discussion interesting where Damian Schenkelman explains the controller purpose in the ViewDiscoveryComposition Quickstart.

 

Going back to your original question, if your scenario is such that only lines can manipulate your points,  you should really consider if using prism regions is the best approach. Using regions might not be necessary and brings some complexities that might be avoided. In general the Region manager acts as a locator, used by external modules to be able to find UI containers defined on other module. So if the only module that will use the StartPoint and EndPoint regions is the LineModule, and also the LineModel needs to know explicitly about these PointModels (although in a decoupled fashion by using interfaces), regions are probably unnecessary.

For example you can just databind each point from XAML to the Control you desire without  creating a region on it.  You can even use automatic DataTemplates to define the View for the PointModels (these won't work in Silverlight though).

 

If you have any doubt just let me know!

 

Matias Bonaventura

http://blogs.southworks.net/matiasb