Monday, July 19, 2004

Implementing MVC in Windows Forms 3.

How is navigation managed in MVC? The controller is responsible for reacting to user interaction; this means that any mouse clicks on buttons or menu items should raise events that are handled by the controller. The controller then reacts by updating the view and the model. The neatest way to do this is to raise a single navigation event, passing up from the form an object representing the view's context and state information. This would contain a snapshot of the model, and any other state information (the values contained in controls, for instance), which the controller can then deal with.
 
This raises a problem; how does the controller decide which forms to display, without hardcoding form names as strings, enum values, or something equally nasty. The MS User Interface Process (UIP) app block deals with this by defining navigation as Xml in the app.config file, but this doesn't fully address the problem (see below).
 
One solution is to take advantage of the fact that the view has a reference to the model. In the navigation event, pass the object in the model (along with state and any other info) that you're interested in, then use this data to dynamically decide which form to display. Using Windows Explorer as an example, your view consists of a treeview containing Drive and Folder objects, and a Listview containing a variety of objects that derive from File. When you right-click one of these items in the view, and select "Properties", you raise an event that indicates a form is to be shown, and pass the model object that was selected (which also contains that object's state); the controller traps the event, gets the Model object, loads a Properties form, and passes the Model object to it so that the state can be displayed. If you need to display different Properties forms based on the type of Model object passed up, then you would switch on the type, and display the relevant form. For instance, a Music file might display a different subclass of the Properties form to that displayed by a text file.
 
But what if the navigation event doesn't have an object model? Such as an About form, or a MessageBox? (Note that apparently the latter causes problems with the UIP block) In my opinion, only when a view event involves the model directly does the controller need to know about it. A MessageBox will usually just be asking for clarification from the user before an action ("do you really want to delete this?") , providing confirmation after an action ("it really was deleted"), or asking for more or clearer information in order to carry out an action ("which item do you want to delete?"). The code required to display and process the MessageBox should not therefore be located in the controller. Show it in the view, handle the user's response, and then raise a navigation event if the user's response warranted one. So, if the user wanted to delete a file, and clicked yes to the MessageBox, raise the delete event so the controller can remove it from the Model and update the view.
 
The About form is slightly different. This will display information about the assembly (version number, etc), and this won't be in your model. That said, the controller really needs to be displaying the About form, so the neatest solution is to raise a specific event (e.g. ShowApplicationDetails) that is handled in the Controller and displays the About form using info taken from the controller's AssemblyInfo file.

0 Comments:

Post a Comment

<< Home