Views and Controllers invisible to each other? How can this be? - actionscript-3

I have read that Views and Controllers should be invisible to each other.
How does the controller then listen for say a button click in the UI view?
Surely the controller needs to know about the view to addEventListeners or the UI view needs to call functions in the controller, or dispatch events to the controller.

My only experience of MVC is with using the robotlegs framework so I'll try explain my approach when using this framework
My views only use native flash events (MouseEvent.CLICK etc) which are listened for in the mediator for the view. When the mediator receives a native event it will then dispatch an application specific event, LoginEvent.LOGIN for example, which can be mapped to then fire a command using the command map on your context.
Sorry if that doesn't make much sense, but basically your views fire native events and your mediators will listen for these native events and then fire application specific events which in turn run your commands. You use the mediator as the 'ears' for your view and keep any logic out of them. The application context allows you to fire commands whenever certain events occur so your views and commands are seperated.

Related

MVVM - Share encapsulated model with other VMs

In my Windows Phone App there's a simple hierarchical model consisting of a class containing a collection of other domain objects.
In my xaml i have declared an ItemsContainer control that renders the items in the above mentioned collection as simple rectangles.
Now, at the VM level i have a structure that resembles my model with a parent VM having a collection of children VMs. Each child-VM encapsulates its own model.
Whenever the user taps the view bound to a child-VM a method of the parent-model object should be invoked taking the relevant child-model as parameter. This will in turn change some internal state that will be reflected (possibly) on all the child-views (not just the tapped one).
SO... given that i'm using the MVVM Light framework my current implementation is as follows:
Child-VM exposes a command
The command Execute method will use the messenger to notify the parent-VM of the tap event. The message (GenericMessage class) content will be the domain object encapsulated by the VM
The parent-VM executes the method of the parent-model using the message content as parameter
If the operation succeeds the parent-VM sends a new message to inform child-VMs of this fact. Once again the message content is the model object used as parameter in the method that was just invoked
Child-VMs raise a couple of PropertyChanged events that, finally, will update the bound views
It works but i fill it's a bit cumbersome. The thing that bugs me the most is the fact that when a child-view is tapped the associated VM will broadcast its encapsulated model object. Do you feel that there would be a better way of implementing such a system?
Thanks in advance for your precious help
Could you not just put the command on the parent viewmodel and pass the child viewmodel as the command parameter?
The parent view model can then just call methods on the child viewmodels to update them. I'm not sure I see the need for all these messages?

Firing a KeyDown event in WinRT

Is there a way to fire a custom KeyUp/KeyDown event on the CoreWindow?
For example, take the following event:http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.core.corewindow.keyup.aspx.
My application already uses CoreWindow::KeyUp and CoreWindow::KeyDown to handle events. I am trying to test that the correct delegates are being attached and thus called when an event happens.
Note that I can't call the delegate function directly since it will not test the fact that the delegate is attached to the event.
I am looking for an answer similar to https://stackoverflow.com/a/3977396/756356.
I doubt that's possible because it sounds like something possibly interfering with the sandbox concept of modern apps. You could maybe insert some layer between the CoreWindow and your handlers and bubble the events through that layer to make is possible to raise your proxy events. I would recommend against that though since that just adds code you don't need.

MVC controller and view relationship

First off, I've done a lot of research on the web (including this site) and have found lots of conflicting information on how the model and controller communicate in an MVC pattern. Here is my specific question (I'm using AS3), but it's a general MVC question...
I have two main components... a list of recipes and a form that displays a selected recipe. The form has an edit state that allows you to edit the recipe and then save or cancel the changes. What is the best way (using MVC principles) to handle changes made to a recipe? So far, I have the save button trigger an event which is captured by the controller.
Should I have the save button (the view) pass an object with the current state of the fields along with the event (some logic in view)? Should I allow the controller to hold access to the view and have the controller figure out what's in the fields on its own (added coupling)? Should events be made every time a field in the form is changed and the controller keeps track of the state of each field (lots of events)? Or is their another way? Note: I don't want to bind the fields to the model because I only want the data to save if the save button is clicked.
Any help would be greatly appreciated. Thanks!
Should I have the save button (the view) pass an object with the
current state of the fields along with the event (some logic in view)?
yes, this is not 'logic in the view', it does not decide anything, simply reporting an action and its current state
Should I allow the controller to hold access to the view and have the
controller figure out what's in the fields on its own (added
coupling)?
no, this would become very messy, pass a VO with the event
Should events be made every time a field in the form is changed and
the controller keeps track of the state of each field (lots of
events)?
is an option, but this basically is the same as hitting the save button, the trigger is different (TextField.onChange), but you can dispatch the same event (setup is form = view, dispatches one general event with a VO, not an event for each field)
Or is their another way?
MVC flow w/ events:
onClick save btn: a RecipeEvent.SAVE is dispatched (from the view), with a VO (value object) containing the Recipe data (e.g. RecipeVO)
the controller catches this, and as the controller is where the logic resides, it decides what to do with it: update the RecipesModel (either directly by calling a method on the model, or by a custom event e.g. RecipeModelEvent.SAVE)
the model stores the data, and dispatches the RecipeEvent.UPDATE event (with the RecipeVO)
the views updated itself accordingly (check if the RecipeVO.ID is same, update data representation e.g. titleā€¦)
optionally, a controller could save the data to a back-end/remote database
As for the event listeners: views listen to the model, controller listen to the views.
About de-coupling:
use interfaces (by using an IModel you can swap out the model easily by another implementation, as you register the event listeners against the interface instead of the actual implementation)
Obviously, all this results in a lot of registering/removing event listeners, and keeping reference to the models/views/controllers to be able to register to the appropriate instance. An alternative is to use a framework as RobotLegs, as it makes a central event-bus available + easy/automatic cleanup of event listeners in the mediator class of a view.
I think this is really a database question. what I would do is create a stored procedure that first checks to see if the recipe already exists. If yes then update it. If not then add a new recipe. (you'll have to bind your entity to a stored procedure. other MVC frameworks can do this. I don't know about actionscript)
if that's not an option then I guess you would have to cache the original form in a helper class in the controller and then compare it to what the user is trying to save. And have the controller decide whether to update the recipe.
I think it's much cleaner to use the first way, but I've never used actionscript so...
Colin Moock's lecture on MVC in ActionScript is quite old, but still one of the best explications: http://www.moock.org/lectures/mvc/
Your model should populate your view, and your view should send input events to the controller, which should decide what to do with the input. As g10 says, wait until the save button is clicked and then pass an object with the modified fields up to the controller for processing. The controller can then decide whether or not to accept it, and whether to update an existing model object or create a new one.

Where to place EventDispatcher in Symfony2 and how to use it with Annotations?

I am starting developing with Symfony2 framework and I like to use the Eventdispatcher. Now I have three questions I could find an answer with google yet.
Where I place the dispatcher so it is accessable from everywhere in
tha app?
How I can configure customevents? Should I place all in one file or
one for each bunble?
How much effort is it to configure it with annotations, i.e
#Event("some.event")? Is that possible?
General
I might suggest the Symfony 2 documentation on the EventDispatcher as a good starting point, assuming that you mean you wish to provide custom events rather than a custom event dispatcher.
Symfony2 Internals - The Event Dispatcher
Location of Events
In terms of location, an 'Event' folder within the appropriate bundle is a good choice. It is likely that the actual dispatching of the event will take place only within the bundle context, whereas listeners may reside elsewhere. This is however a separate topic and of minimal relevance as they simply subscribe to the event's string-name (e.g., 'store.order' to borrow the documentation's example) and only require knowledge of the Event's interface/type.
So you might have an Event called 'Foo' within the 'Bar' bundle in 'Zap' namespace:
namespace Zap\Bar\Event;
use Symfony\Component\EventDispatcher\Event;
class FooEvent extends Event
{
// ...
}
When you then come to dispatch an event from within your bundle, you might choose to use the event identifier 'zap.bar.foo', and of course you can then register listeners from elsewhere to be notified on this identifier as you see fit.
Accessing the Event Dispatcher
Where you wish to access the primary EventDispatcher instance, acquire access to the Dependency Injection Container and retrieve the 'event_dispatcher' service. A simple approach is to have your class extend 'ContainerAware' and then retrieve the dispatcher with
$dispatcher = $this->container->get('event_dispatcher');
To answer your first question:
Where I place the dispatcher so it is accessable from everywhere in tha app?
Actually, there is already preconfigured event dispatcher service accessible, as #jstephenson pointed out, by calling $dispatcher = $this->container->get('event_dispatcher'); so you don't have to create your own instance anywhere.
However, if you need your own event dispatcher, you can simply configure it in your services configuration file (i.e. services.xml) of your bundle like this:
<service id="my_dispatcher" class="Symfony\Component\EventDispatcher\EventDispatcher" />
You can of course use your own dispatcher class as long as it implements EventDispatcherInterface.

How do I attach a global event listener?

I am working on an AIR application:
The main window is like a dashboard. With the menu bar, I can open other windows with dashboard details. When I close these, I'd like to refresh the main window.
I tried to use an event listener, but the result is not good. If I open detail windows directly from the main window, I know how to add an event listener - and it works - but I don't know how to do it, if the detail window is opening from the menubar!
Thanks for helping me.
A Singleton is what you are looking for. Just put an event dispatcher inside and you will be able to listen from everywhere in the application.
A Singleton is like having a unique instance of an object in memory, so anyone modifying a variable inside that object ( or sending events throught ) will be modified for everyone.
Here is an example of code on how to use it.
http://life.neophi.com/danielr/2006/10/singleton_pattern_in_as3.html
Note: Singletons are powerful and dangerous at the same time, there is a lot of talk about how to use them, please read a little more about that if you are considering building a big project.
Hope it helps!
The issue is that you're performing business logic from a View. Don't do this. Instead, dispatch an event from each menu rather than directly opening the window from within it. Listen for those events at a higher level, and then you can either directly listen to the new windows you have opened, or you can create a base window Class that exposes a variable of type IEventDispatcher. If you populate that variable with the same event dispatcher, what you wind up with is called an "event bus," and you can listen on that for events.
This architecture requires a little more thought than using a Singleton, but it avoids the tight coupling and other issues you'll run into by introducing one into your project.
You can listen to an object (EventDispatcher) directly by adding an event listener to it, or if the dispatcher object is on the displaylist, such as a Sprite, you could listen at the stage level with the capture parameter set to true.
But the main caveat is that the dispatcher must be on stage for you to catch this event.
Your main window listens to stage (with capture = true):
stage.addEventListener("MY_CUSTOM_EVENT", handle_custom_event, true);
private function handle_custom_event(e:Event):void
{
var sub_window:Object = e.target;
// do something to your sub_window
}
Your sub window can dispatch events like this:
dispatchEvent(new Event("MY_CUSTOM_EVENT"));
But (ab)using the stage as a message passing infrastructure for custom events in this way is a little messy. You could consider a more formal message passing architecture if you really want this kind of communication. Even a static MessageBus class would at least quickly help you identify where you use this in your codebase. Either way, you'll have to be careful about references and memory leaks.