I am trying to use Prism.
I use Regions in Region. Main region contains two sub regions.
My problem is when I change my main region then the method "OnNavigatedFrom" of INavigationAware interface implementation is not invoking.
But When I change only one of sub regions then this method is invoking.
I need that the method always is invoked.
Does anyone have an idea?
The methods in INavigationAware are called when a region is navigated. It will not call those on parent or child regions.
The solution is to make the navigated region do the work. So when the main region is navigated, it should doe whatever cleanup is needed in its child regions.
Related
I'm trying to implement modularity and have some complications. I implemented one module which called ModuleA which shows new childWindow in its initialize function;
public ModuleA()
{
personViewModel = new PersonViewModel();
detail = new ViewDetail(personViewModel);
}
public void Initialize()
{
detail.Show();
}
My problem is that i can't show the view again because of missing opportunity of reload function. My module loaded on demand, i mean that i want to load module when user clicks button so, i do not have a chance to load module at the beginning and control its functions from its own events. then i tried to show view from my application like that;
private void ButtonModelA_Click(object sender, RoutedEventArgs e)
{
this.moduleManager.LoadModule(MyBootstrapper.ModuleAName);
ChildWindow detail = new ModuleA.ViewDetail(new ModuleA.ViewModel.PersonViewModel());
detail.Show();
}
in this way, loading module became unnecessary.
Is there a way to load module from out of it as on demand and show its view multiple times ?
I'm not quite sure how this works in Silverlight, but I think there is a misunderstanding of Prism.
Prism is based on regions. That means that the applications user interface consists of ContentControls (or other region capable controls) that state to be a region. The region manager now adds all views that want to reside inside a specific region into exactly this region.
The modules just have to tell the region manager inside which region the views implemented in the specific module wants to reside:
RegionManager.RegisterViewWithRegion( "RegionName", typeof( View ) );
If the specific region is currently not a part of the user interface, because the view that contains the control that hosts the region isn't part of the user interface itself, the view that wants to resied inside the region cannot be placed inside this region. The region manager just doesn't know of the region. To have the view shown you have to add the control that hosts the region to the user interface by hand.
Another way is to add a specific into a region by hand. Using this approach you don't have to register the view to the region manager. So when the region manager discovers the region it stays empty. Now you can add the view manually into the region using the region manager:
IRegion region = RegionManager.Regions["RegionName"];
region.Add( new View(), "ViewName" );
If you want to place views into a region depending on any state or user action you have to add the into the region by hand. Have a look at the Stock Trader Reference Inplementation. It explains in a very simple manner how to add views to regions triggered by user action.
I have a button in a Window that needs to call a function in pages contained within a frame. The page inside the frame will change based on a navigation contained in the main Window, so I will know the current Page within the frame.
Can someone help with how to call function in frame pages?
If you wish to approach this from an MVVM perspective, you'll want to make sure you're not working with the actual view here, but the ViewModel abstraction of it. In that case, your parent Window is probably backed by a ViewModel that contains some sort of a collection that backs your pages in the frame/tab control/container of choice. In that case, the button should link to a command on your Window-backing ViewModel and use the selected item in the collection to access the function. If you do not have a direct reference in this fashion (for example loading in from another module or something for frame contents) you can also use EventAggregator from the Prism/CAL libraries and publish an event when the window button is pressed and set up your pages to receive that event and handle the call there. EventAggregator can be a slick way to handle cross-module logic in a clean way.
I'm writing an application in Prism. I have a user control and contains two <ContentControl> controls. These both have Regions assigned to them. The usercontrol is being hosted in a Window that is being shown using ShowDialog().
I'm adding the one of my views to a region using view discovery and the other I want to inject the view into its region. The view discovery works fine. However when I try and reference the other region to inject the view I get the exception:
KeyNotFoundException
The region manager does not contain the MyRegion region.
When I look in the RegionManagers regions neither the one that I'm trying to inject the view exists or the one being that's using view discovery.
Does it matter that I'm in a different window to the Shell? I thought there was only one RegionManager, but there must be two for my view discovery to still be working...? Or is it because I have two new regions being created later in the applications life cycle? Or is it because the new regions aren't inside the my MainRegion?
EDIT:
After doing some digging it looks like the Region is created but it can't find an instance of the RegionManager so it doesn't get added. Any clues?
Sorted now. I needed to register the region manager in the constructor of my presenter class.
That way the regions in my new window could find my global region manager.
RegionManager.SetRegionManager(view as DependencyObject, regionManager);
i am working on MVVM and using commanding in silverlight(DelegateEvent and ICommand)
I want something like this ,(say) i have 2 usercontrols , parent and child .
Parent is hosting the child , both have thier own viewmodels .
On parent i have a button and it executes a simple command , on execute of that command i want to update text in the child control's textbox . also we should be able to change something in child which can propagate to the parent .
Is events the best answer for this or i can have commands to update child/notify parent in some way.
There are several ways to go about this.
First, it is completely appropriate to have ViewModels that are composed of other ViewModels, as long as you are OK with them being coupled in that way. When you do that, they can just talk to each other using regular method calls.
Next, you can decouple a bit and use events. Nothing wrong with that. There is still an Observer -> Observable coupling, but they are less dependent upon each other.
Next, you can completely decouple and use something like an EventAggregator (Prism has a good one you can use). Shoot a Publish a message. The other subscribes. They don't know about each other at all.
I have used commands for this as well... but for ViewModel to ViewModel communication, I find this to be a bit awkward.
You should probably start with most obvious implementation where parent viewmodel simply holds a reference to a child viewmodel, and child viewmodel holds a reference to a parent viewmodel. Then when a command is executed on parent viewmodel it simply sets a value on a child viewmodel to which textbox is bound to.
Adding a layer of abstraction between parent and child (e.g. events) adds a level of complexity and as a result it should be justified. If the value this indirection provides is higher than the cost of increased complexity of the code (e.g. it's now less clear what happens when command on a parent is executed, you will have to solve a problem how child gets subscribed to parent's event without obtaining the actual reference to it and vice-versa, adding additional dependencies between parent a child will require adding additional events, which pollutes the actual logic with all the plumbing, etc.) then certainly events (or something like PropertyObserver) might be a next logic step.
This seems like an ideal situation for using an EventAggregator like the one in the Composite Application Guidance / Prism.
In this model, you can set up a MessageBus in the root of the application (or other common area).
// in App.xaml.cs
public static IEventAggregator MessageBus = new EventAggregator();
Then set up a common Messages library
// in Messages.cs
public class SimpleCommand: CompositePresentationEvent<SimpleObject> { }
Where SimpleObject is a class or variable that contains all the info necessary to process this event.
// in control with button
App.MessageBus.GetEvent<Messages.SimpleCommand>().Publish(SimpleObject);
// anywhere in your app that you "care" about this
App.MessageBus.GetEvent<Messages.SimpleCommand>().Subscribe(ProcessingMethod);
Where ProcessingMethod is a method that takes a SimpleObject as a parameter.
Then you can spout off messages from anywhere and process them anywhere - across viewmodels, controls, etc. You can even pass MessageBuses between components if you are dynamically loading parts of the app. Works well.
I'm trying to get better at using MVC/MVP style patterns with my WinForm apps and I'm struggling with something that maybe someone here with more experience can help me with.
Below is my basic project layout:
The class G2.cs handles the running of various threads and includes a Start/Stop and other various methods involved with those threads. It is my "main" class I suppose. It contains the main loop for my application as well.
My GUI is composed of 3 forms so far and an associated controller for each. The MainForm has Start/Stop buttons that need to call methods on my G2 class as well as possible future forms.
What would be the correct way to pass a reference of my G2 class to all the view's controllers who need it? Do I need to pass the G2 reference to the Form when I create it and the form in-turn passes it to my Controllers or... is that not a good way to handle things?
Also, am I correct in that it is the Views responsibility to create an instance of it's controller and it "owns" the controller?
If G2 is main program class, and exists only in one instance, I would use singleton pattern on this class - no need to passing references.