I have a fairly large prism app and am trying to app a new feature. The feature is a serial port parameter selection.
I want to refresh the list of serial port names when my viewmodel's IsActive property is set to true. This is happily achieved in a sample but reality is...different.
The view i am modifying is contained in an ItemsControl (marked as "SettingsRegion") which is contained in a parent region ( marked as "PageRegion"). Settings region contains settings views from other modules.
I want to use the SyncActiveAwareAttribute for this but it requires scoped regions.
Do I need to use view injection (regionmanager.Regions["blahblah"].Add(....) here or can i get it working using view discovery (regionManager.RegisterWithRegion(...)?
If I have to use injection...
Given that the other modules would need a reference to the scoped IRegionManager instance in order to inject their views:
how is the best way to get the region manager to the other modules?
when should injection take place to ensure that the region exists?
can i mix-and-match injection with discovery? I want to avoid a big refactor.
In order to create Scoped Regions, you would need to use View injection. Related information can be found in the following MSDN Prism Chapter #7 links:
When to Use View Discovery vs. View Injection
Creating Multiple Instances of a Region
The Scoped Region Manager is returned by setting the createScopeRegionManager overloaded parameter as true on the Region.Add() method. You would perform this action in the same place you usually add or register Views into Regions like on the corresponding Module's initialize() method:
IRegionManager scopedRegionManager = scopedRegion.Add(view, null, createScopeRegionManager);
Then, one possible way of sharing the scopedRegionManager to other modules would be to Publish() an event with the scopedRegionManager as a parameter. However, you should be careful with Module dependencies and the Modules instantiation order.
Another approach would be to store the scopedRegionManager into for example, a Dictionary. You can find more related information in the following CodePlex thread:
Scoped Regions in TabControls
It should not be any problem by using View Discovery on other Views registration that would not present Scoped Regions.
I hope this helped you,
Regards.
Related
I am a total newb to Spring. Even though I understand the concepts of individual annotations (and dependency injection), I am having difficulty "seeing the forest for the trees." Here, in this example, I have a page that has a dropdown box. It also stores the user's selected option from that box. So there are three beans, only one of which is properly called a domain bean:
DropDownEntry *domain
SelectedOption (which could be String or a whole DropDownEntry type stored at Session Scope)
PageModel (containing a List of #1 above, and a single instance of #2)
Below is an image of my best guess as how to use Spring to:
1. Retrieve a List from the persistence layer via DAO
2. Retrieve/Store the user's selection
Is this design remotely near correct? Is there an alternate "best practices" way to architect this scenario?
I think Spring MVC Forms might be what you are looking for.
http://www.javacodegeeks.com/2013/07/spring-mvc-form-handling-vol-5-select-option-options-tags.html
Model
The model is a map of entries for the drop down box.
Controller
You can fetch these entries from a database using the DAO Pattern and turn it into a map in a controller class.
View
The drop down box is generated using a mix of HTML, a JSP tags and map of 'drop-down' entries.
Hard to tell. But from the looks of it, you've made things awfully complicated.
My advice: stop drawing UML, re-read the specification, and start coding. Start with a simple model class that represents the selectable entity. Don't name it DropDownEntry (unless you're creating software to model dropdowns), but something that actually describes the selectable entity. Don't worry about data access (DAOs) at this point.
Then create a controller class that allows you to render a view that contains the said dropdown UI element. Then pass the selectable entities (as reference data) to the view in the model. Then make the view render the selectable entities appropriately. Then allow the user to post the selection back to your controller.
Once you have this, you can think about saving the selected entity to persistent storage. At that point you will probably find out that you need to link the selected entity to a user etc.
Good luck.
I've been using Ember for a while but still struggling sometimes to find out the best practices. So one of the Ember ways regarding controller and view is
an opinion of Ember's designers, that is enforced by the router is that for a given BaseName (e.g. "Application," "CustomerEntry," "My Items") there should be a BaseNameView and a BaseNameController. -- Ember guide
The problem is that what if I want multiple instances of the same view on a page. Since the controller is created during initiation of the application, they are singletons under the application namespace, which will not be able to hold two instances of the model data.
One solution I see is to create controllers(and model data) manually and pass them to views. But in this case, I'd like Ember not create controllers automatically for me. Put it another way, why would Ember creates controllers as singletons during application startup.
I think there are many use cases where a View type doesn't have a corresponding Controller type. Especially when the type of view is more like a UI widget than a full-fledged application feature. Many views can share the same controller. Take a look at this applicationView template:
<h1>Here are two files, compare them</h1>
{{view App.MyFileView contentBinding="leftFileContent"}}
{{view App.MyFileView contentBinding="rightFileContent"}}
This creates two instances of my view class and binds their content properties to two different properties on the applicationController. The controller property for both of those views is set to the singleton applicationController instance.
One possible reason why controllers are singletons could be that they're able to be addressed in the global namespace via something like App.router.myController.
If I have a collection which contains a list of models and want to create corresponding views for each model, what is the best way to do this using IOC (inversion of control)?
I see two ways:
Use a factory pattern. I would only pass in my model collection and build views as I need them with a factory that is passed in via IOC.
Create a another class which would have a list of all the views I need, pre-built by the IOC. Then I just pick the view I want from the list.
Which way do you think is better?
If you can build the Views in advance the best solution might be to simply inject a list (IEnumerable) of all the Views into each consumer and perhaps use the Specification Pattern to select the appropriate View from that list.
If, on the other hand, you need run-time values before you can instantiate each View, a Factory is the correct solution.
In Composite WPF (Prism), when adding modules to the IRegionManger collection, what is the difference between using IRegion.Add and IRegionManager.RegisterViewWithRegion?
IRegion.Add
public void Initialize()
{
_regionManager.Regions["MainRegion"].Add( new ModuleAView() );
}
IRegionManager.RegisterViewWithRegion
public void Initialize()
{
_regionManager.RegisterViewWithRegion( "MainRegion", typeof( ModuleAView ) );
}
The difference is who is responsible for creating the view. In the IRegion.Add scenario (also called View Injection) you are responsible for instantiating the view beforehand. In the other scenario with RegisterViewWithRegion (also called View Discovery), the region manager instantiates the view itself.
There are some technical reasons you would want to do one or the other. For example
you had a more complicated way of creating views (maybe you want to create the View and its ViewModel and marry them by setting the DataContext property yourself), you'd need to use View Injection
if you take advantage of Region Scopes, you will be forced to use View Injection.
The relevant documenation is:
For View Composition (including View Injection vs. View Discovery and discussions of View-First or View-Presenter-First approaches):
http://msdn.microsoft.com/en-us/library/dd458944.aspx
There's also a really handy "when to use each" section. Here's the excerpt from the docs:
Explicit or programmatic control over when a view is created and
displayed, or when you need to
remove a view from a region, for
example, as a result of application
logic.
To display multiple instances of the same views into a region, where
each view instance is bound to
different data.
To control which instance of a region a view is added (for
example, if you want to add
customer detail view to a specific
customer detail region). Note that
this scenario requires scoped
regions described later in this
topic.
Hope this helps.
RegisterViewWithRegion raises the OnContentRegistered event, but of course that could not be the case depending on your DI
I have two classes that each need an instance of each other to function. Ordinarily if an object needs another object to run, I like to pass it in the constructor. But I can't do that in this case, because one object has to be instantiated before the other, and so therefore the second object does not exist to be passed to the first object's constructor.
I can resolve this by passing the first object to the second object's constructor, then calling a setter on the first object to pass the second object to it, but that seems a little clunky, and I'm wondering if there's a better way:
backend = new Backend();
panel = new Panel(backend);
backend.setPanel();
I've never put any study into MVC; I suppose I'm dealing with a model here (the Backend), and a view or a controller (the Panel). Any insights here I can gain from MVC?
It's time to take a look at MVC. :-) When you have a model-view-controller situation, the consensus is that the model shouldn't be aware of the view-controller (MVC often plays out as M-VC), but the view is invariably aware of the model.
If the model needs to tell the view something, it does so by notifying its listeners, of which it may have multiples. Your view should be one of them.
In a circular construction scenario I'd use a factory class/factory method. I would normally make the construction logic private to the factory (using friend construct, package level protection or similar), to en sure that no-one could construct instances without using the factory.
The use of setter/constructor is really a part of the contract between the two classes and the factory, so I'd just use whichever's convenient.
As has been pointed out, you really should try to find a non-circular solution.
First of all, contrary to what others has said here, there's no inherent problem with circular references. For example, an Order object would be expected to have a reference to the Customer object of the person who placed the Order. Similarly, it would be natural for the Customer object to have a list of Orders he has placed.
In a refernce-based language (like Java or C#) there's no problem, at all. In a value-based language (like C++), you have to take care in designing them.
That said, you design of:
backend = new Backend();
panel = new Panel(backend);
backend.setPanel(panel);
It pretty much the only way to do it.
It's better to avoid circular references. I would personally try to rethink my objects.
panel = new Panel(backend);
You do this in this routine something like
Public Sub Panel(ByVal BackEnd as BackEnd)
Me.MyBackEnd = BackEnd
BackEnd.MyPanel = Me
End Sub
You don't need BackEnd.SetPanel
It is better to use Proxies. A proxy links one object to another through raising a Event. The parent hands the child a proxy. When the child needs the parent it calls a GetRef method on the proxy. The proxy then raises a event which the parent uses to return itself to the proxy which then hands it to the child.
The use of the Event/Delegate mechanism avoids any circular reference problems.
So you have (assuming that the backend is the 'parent' here)
Public Sub Panel(ByVal BackEnd as BackEnd)
Me.MyBackEnd = BackEnd.Proxy
BackEnd.MyPanel = Me
End Sub
Public Property MyBackEnd() as BackEnd
Set (ByVal Value as BackEnd)
priBackEndProxy = BackEnd.Proxy
End Set
Get
Return priBackEndProxy.GetRef
End Get
End Property
Here is a fuller discussion on the problem of circular references. Although it is focused on fixing it in Visual Basic 6.0.
Dynamic Memory Allocation
Also another solution is aggregating Panel and BackEnd into another object. This is common if both elements are UI Controls and need to behave in a coordinated manner.
Finally as far as MVC goes I recommend using a a Model View Presenter approach instead.
Basically you have your Form Implement a IPanelForm interface. It registers itself with a class called Panel which does all the UI logic. BackEnd should have events that Panel can hook into for when the model changes. Panel handles the event and updates the form through the IPanelForm interface.
User clicks a button
The form passes to Panel that the user clicked a button
Panel handles the button and retrieves the data from the backend
Panel formats the data.
Panel uses IPanelForm Interface to show the data on the Form.
I've been delaying implementing the lessons learned here, giving me plenty of time to think about the exact right way to do it. As other people said, having a clear separation where the backend objects have listeners for when their properties change is definitely the way to go. Not only will it resolve the specific issue I was asking about in this question, it is going to make a lot of other bad design smells in this code look better. There are actually a lot of different Backend classes (going by the generic class names I used in my example), each with their own corresponding Panel class. And there's even a couple of places where some things can be moved around to separate other pairs of classes into Backend/Panel pairs following the same pattern and reducing a lot of passing junk around as parameters.
The rest of this answer is going to get language specific, as I am using Java.
I've not worried a whole lot about "JavaBeans," but I have found that following basic JavaBean conventions has been very helpful for me in the past: basically, using standard getters and setters for properties. Turns out there's a JavaBean convention I was unaware of which is really going to help here: bound properties. Bound properties are properties available through standard getters and setters which fire PropertyChangeEvents when they change. [I don't know for sure, but the JavaBeans standard may specify that all properties are supposed to be "bound properties." Not relevant to me, at this point. Be aware also that "standard" getters and setters can be very non-standard through the use of BeanInfo classes to define a JavaBean's exact interface, but I never use that, either.] (The main other JavaBean convention that I choose to follow or not as appropriate in each situation is a no-argument constructor; I'm already following it in this project because each of these Backend objects has to be serializable.)
I've found this blog entry, which was very helpful in cluing me into the bound properties/PropertyChangeEvents issue and helping me construct a plan for how I'm going to rework this code.
Right now all of my backend objects inherit from a common class called Model, which provides a couple of things every backend in this system needs including serialization support. I'm going to create an additional class JavaBean as a superclass of Model which will provide the PropertyChangeEvent support that I need, inherited by every Model. I'll update the setters in each Model to fire a PropertyChangeEvent when called. I may also have JavaBean inherited by a couple of classes which aren't technically Models in the same sense as these but which could also benefit from having other classes registered as listeners for them. The JavaBean class may not fully implement the JavaBean spec; as I've said, there are several details I don't care about. But it's good enough for this project. It sounds like I could get all this by inheriting from java.awt.Component, but these aren't components in any sense that I can justify, so I don't want to do that. (I also don't know what overhead it might entail.)
Once every Model is a JavaBean, complete with PropertyChangeEvent support, I'll do a lot of code cleanup: Models that are currently keeping references to Panels will be updated and the Panels will register themselves as listeners. So much cleaner! The Model won't have to know (and shouldn't have known in the first place) what methods the Panel should call on itself when the property updates.