PRISM: Passing object/events from parent to child View/VM with PopupRegions - events

We are working with an application that uses prism and MVVM for healthcare tracking operations.
Within this application, we have registered views in primary regions, and scenarios in which clicking on a cell in a grid (in this case a xamdatagrid - Infragistics) will launch another region via the prism region popup behaviors constructs.
So, when we click on the cell, a cellactivation operation in the code behind for that view is called which then calls a method in the view model to .RequestNavigate to the view that is registered for the 'secondary' popup region (thus launching what appears to be a dialog over the existing application).
I am attempting to pass an object from the parent view (the values of the record in the grid) to the child view that is launched in the popup, and have found that none of the expected operations is working.
I have a mediator object that we are using to pass information back from children to parents, but this does not work the other direction because the publish/notify operations for the mediator require the child view to 'already' be instantiated before the parent publishes to pass that information.
I'm finding that the event aggregator structures built into the Prism.Events classes don't appear to be working either (I'm assuming because of the same publish/subscribe issues). I can publish an event through the event aggregator from the parent view and subscribe in the child view, but I have to launch the child view 'twice' in order to get the event tied to the event aggregator operation to actually fire.
I understand this is rather vague (minus the code), but I'm looking more for a start point, or anyone that's run into the same kinds of issues. The bullet point scenario is as follows:
Parent view already instantiated in existing region.
Clicking on cell in parent view instantiates (navigates to) child view in popup region.
Same click operation needs to pass an object from the parent view to the child view so that the child view can filter its own data based on that object.
Operations are constructed using Prism/MVVM.
Any help, suggestions, pointers, ideas would be awesome.

We had the same scenario and ended up with creating a UiService that are injected to our ViewModels. Our ViewModel base class has a SetModel method which the UiService calls when navigating, for sending parameters to the destination view.
By example:
Clicking a button in the existing View.
Source ViewModel calls UiService ShowView(data).
UiService calls RequestNavigate for the requested view.
UiService calls SetModel on the destination ViewModel (by accessing the DataContext of the requested view) to pass in the data from the source ViewModel.

Depending what you want to pass it can be pretty simple with INavigationAware
Sounds like you want to pass something like query string - parameters, etc. Code to open window will be like this:
var query = new UriQuery
{
{ "MailItemKey", this.SelectedMailItem.MailItemKey.ToString(CultureInfo.InvariantCulture) }
};
RegionManager.RequestNavigate(RegionNames.Popup, typeof(MailItemView).Name + query.ToString());
And inside MailItemViewModel which is our popup's VM code is like this:
public override void OnNavigatedTo(NavigationContext navigationContext)
{
var mailItemKey = int.Parse(navigationContext.Parameters["MailItemKey"]);
}
If you want to pass custom objects - it will be more complex. I would look for MVVM in the box samples - there is some code on how it's done. I had to re-work it whole lot and code is not really copy-pasteable.

Sounds like a perfect use of a RegionContext.
Parent view contains a region that can have multiple "child" views activated in it. They need to share some context or data. Set a region context and bind or pass whatever info all the "child" views in the Region will need.
See the Prism samples around RegionContext.

Related

Laravel multiple model bound forms in a parent view

The overall concept that I'm attempting to do is create admin panel that has multiple "forms" on a single blade view. Each "form" is a blade.php file that has a form that is model bound to provide quick access to the model data on load. For example, let's say that I'm running a manufacturing line and there are three models (subviews) that I want to #include() on manufacturing.blade.php.
Parent view (manufacturing.blade.php)
Subview - Start time (start-time.blade.php)
Subview - Throughput (throughput.blade.php)
Subview - Supervisor (supervisor.blade.php)
Each subview has a submit button on it that POSTS to the assigned resource controller. My problem is how do I successfully load manufacturing.blade.php and include form model binding when I never call the index controller on the subviews.
Is what I'm asking even possible?
For what it's worth I figured it out right after I posted the question. The variables required for the model binding inside the subviews were the problem. I was receiving errors about the variables not available, blah.... when I loaded the parent view page. Obviously the variables aren't available when I call the subviews because they were never pulled in from the parent view. In other words I'm trying to access something that isn't there.
Solution:
In the parent view loading controller, perform all the necessary db call to obtain/generate the objects required for the subviews. After the objects are obtained use
View::share('startTime', $startTime);
View::share('throughput', $throughput);
View::share('supervisor', $supervisor);
That method (view::share) allows that variable, 'startTime', etc..., to be shared across all the blade views that reside inside of parent. Just be sure you add the lines right before you return the intended parent view from your controller.

Cocoa MVC: interaction between "model controller" and "view controller"

Just started learning Objective-C and Cocoa with the help of BNR's Cocoa Programming for Mac OS X (4th Ed.), and I'm working on a document-based application. I've read through Apple's developer documentation on the document architecture, and have chosen to subclass NSWindowController and override makeWindowControllers on my NSDocument subclass. I have a few reasons for doing this:
to separate model logic (in NSDocument subclass) from view logic (in NSWindowController subclass).
to customize the title of my document windows (Apple's developer documentation says that the proper way to do this without unwanted side effects is to subclass NSWindowController and override windowTitleForDocumentDisplayName:
Apple's documentation seems to strongly suggest subclassing NSWindowController for all but the simplest of applications, and mine is definitely not "simple"
So, my NSDocument subclass is a model controller, and my NSWindowController subclass is a view controller. Further, I understand that most of an application's "work" is done in the controller objects, as the views and models should be as application-agnostic and reusable as possible. Now comes my question: how do these two types of controllers interact to actually do this "work"?
For example, imagine I'm writing a spreadsheet application, and I want to have a menu item (or toolbar button) that brings up a sheet for creating a chart or graph from some of my data. In that sheet, the user will enter various parameters and options for how to create the chart or graph, then click "OK" (or whatever the button is called).
Who should respond to the menu item's action, the document (model controller) or the window controller (view controller)? The task of actually loading and showing the sheet seems decidedly "view-related", so it should go in the window controller, correct? But the controller for the sheet needs a model to display to the user (a Chart object, or maybe ChartInputs); where does that model get created and given to the sheet controller? Should the document respond to the menu item by creating the ChartInputs model object, then pass that to the window controller, which creates the sheet controller, passing it the model object, and shows the sheet? Or should the window controller respond to the menu item, request a new model object (perhaps through some sort of factory provided via dependency injection into the constructor of the window controller), then proceed with creating the sheet controller, passing the model, and showing the sheet?
What about after the user fills out the sheet and clicks "OK"? Where should control be returned to process the user's choices and actually create the chart -- window controller, document, or both? What about logic to validate the user's inputs after they click "OK", but before the sheet is dismissed (in case something is invalid)?
To begin, consider windowless operation of your NSDocument. For example, you might create a utility application which shares your NSDocument class, opening documents for scripting, printing, or other manipulation, but without presenting your primary document window. Imagine your NSDocument class reused for that application – and put the logic you wouldn't want into your window controller. This way, the NSDocument subclass is primarily responsible for activities which affect the document's state.
These are the responsibilities of the model-controller (NSDocument subclass):
Serialization and deserialization
Loading and saving
Manipulating the document's state
Managing and dispatching print views
Monitoring the document for changes by others
Refreshing supporting data sources – sources which affect the document model – and applying changes to the model and document as needed
Managing an activity log related to the document
Owning the undo manager
Exposing the essential model objects to the view controller
Creating window controllers
Facilitating some editing behaviors, such as a change to one property triggering creation or removal of objects
If you're using Core Data, your managed object context, persistent store coordinator, and persistent store are part of the model-controller, not the model. Of course the managed objects themselves are part of the model.
This leaves these responsibilities to the model:
Helper methods for inserting, rearranging, and deleting model objects
Helper methods for accessing specific parts of the model
Data validation
Rendering the model to strings, in various formats
Serializing and deserializing oneself
Facilitating some editing behaviors, such as a change to one property triggering changes to other properties
On the other side, these are the responsibilities of the view-controller:
Manipulating the view to keep it in sync with the model
Manipulating the view to keep it in sync with the document state
Responding to localized actions, such as a button which adds or removes a model object
Presenting auxiliary views and responding to input in those views
Dispatching actions which are affected by selections in the UI, such as the selected rows in a table view
Managing auxiliary controllers used during editing, which are not related to the document itself (such as web-service data)
Serving as a data source for view objects
If you're using Cocoa Bindings, your bindings also part of the view controller.
This design produces a reasonable separation of responsibilities between the view-controller and model-controller. However, they both sit between the view and model. While this produces modularity it doesn't produce decoupling.
Though I did consider windowless operation, I largely arrived at this design pattern empirically – by placing similar code together and separating code that felt out-of-place. I'm curious if others post authoritative sources or references which agree or disagree about how to do this.
To take up your example, I'd suggest this design:
EditorWindowController creates ChartParameters object and gives it a reference to the document's model:
[[ChartParameters alloc] initWithWorkbook:self.document.workbook]
EditorWindowController sets up the new-chart view, which probably has its own NewChartViewController. It passes the ChartParameters and document objects to the NewChartViewController and displays the window.
The ChartParameters object is responsible for validating the user's choices. The NewChartViewController needs to manipulate the view to keep it in sync with the validation result. (Avoid letting the user make a mistake: don't wait until the end to validate the input.)
When the view finishes, the NewChartViewController asks the model to create a new chart using the given parameters:
[self.document.workbook addChartWithParameters:self.chartParameters]
If you want the not-yet-a-chart object to be part of your document, you can do is this way instead:
EditorWindowController asks document model to create a new chart object:
Chart *newChart = [self.document.workbook addChart]
Thew new chart should have a flag set, indicating it's not ready for display.
EditorWindowController sets up the NewChartViewController, passes it the chart, displays the window.
Chart object validates the users's choices and the NewChartViewController keeps the view in sync.
When finished, tell the chart it's ready for display. Or if the user cancels, remove it.
In either of these designs, NewChartViewController is a model-controller and view-controller in one, localized for its particular task.

Correct MVC approach for communication between classes of a custom component in JavaFX 2

I have a custom JavaFX-2 component written in the fxml language (Which I'll referrer as child or children), which I used the JavaFX Scene Builder to create it. One of my view classes need to display several (~100) of those components and communicate with them. With the MVC architecture in mind, what's the best approach for communication?
(Container) Model -> (Children) Model
(Container) Controller -> (Children) Controller
(Container) Controller -> (Children) Model
Basically I need at least to be able to monitor 2 case of events happening in the children UI and or in the container object.
Case 1: The user clicked a button (or interacted with another object) which exists inside my custom component (child), the container must be communicate about the change.
Case 2: The user triggered an event on the container, filtering the components based on a specific query for example, I need to communicate the children about this change.
Thanks in advance for all the help. Cheers
I always tend to keep communication between the controllers, while my models are POJOs although they use javafx properties to store data. This seems to map to option #2.
It is fairly easy for the parent controller to call the child controller, all it has to do is load them and keep them in a list. The child calling the parent is a little more ugly since it might require a reference to the parent. I try and avoid this by having an event handler property on the child controller which the parent adds a listener to. This has made my child controls quite reusable.

Creating UI components dynamically in a Model-PassiveView-Controller

In a GUI application, I am using an MVC with a Passive View, as described here.
This pattern is yet another variation on model-view-controller and model-view-presenter. As with these the UI is split between a view that handles display and a controller that responds to user gestures. The significant change with Passive View is that the view is made completely passive and is no longer responsible for updating itself from the model. As a result all of the view logic is in the controller. As a result, there is no dependencies in either direction between the view and the model.
So far, my Controller registers as a listener to existing, static components created by the Passive View itself at initialization. Now, the Controller needs to dynamically create a variable amount of UI components, depending on the Model (concretely, right now I am talking of a grid of checkboxes - the grid's dimensions is variable).
Here is where my hesitation lies:
Should this dynamic UI creation code be implemented in the Controller? This would lead to less complex code resulting from keeping the View unaware of the Model, but a part of the presentation would be decided by the Controller...
Should the View propose a generic, Model-independent way to create the UI components on demand, let the Controller use it and register listeners to the retrieved UI components? Here the Controller would have to convert back and forth between Model objects and generic objects (concretely, strings, integers, ...).
Whenever a view needs dynamic control creation, it tends to be for a collection of something. This means your Presenter/Controller does not need to create all of the logic, but call a method on the view which will create the controls.
On the View:
void PopulateUserOptions(IEnumerable<String> options)
{
foreach (var item in options)
{
\\create and add your controls to the form
}
}
This way the controller is expressing when a controll should be created etc, but leaving it to the view to decide how to do it.

Switching between NSViewControllers

I'm developing a Mac Application. The application has a common source view on the left and a detail view on the right which is the main part of the whole window.
It's like a Master-Detail relationship, but each element in the source view require another detail view. In fact, I have designed a specific NSViewController for each element in the source view.
If I'm switching between these NSViewControllers, that means If I select another element in the source view, I remove the current view and add the view of the newly selected NSViewController. Everytime I change the NSViewController, its state will be lost. When the user comes back to that NSViewController, he has to start over.
My question now is: How can I save the state of the NSViewController, so that I can switch between these without losing its states and can continue where I have left?
Two considerations about your problem:
Keep model data in model classes. This means that you can always recreate a view controller and set its represented object provided the model classes have kept the changes made via the view controller. When you need to instantiate a view controller, set its represented object to (a representation of) a model class.
When removing a view from its superview, you do not necessarily need to release its corresponding view controller. Instead, you can keep strong references to all view controllers in your window controller/application delegate, so no state is actually lost.
Use NSArchiver. Implement archiving/unarchiving in your dealloc/init methods and store each view controller's state in a file named after the class (if you have one item per view controller policy). Otherwise think of some simple naming convention and use it.

Resources