Document/View Model - Advice Sought!

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I'm building my first major C# program and am try to use best practices
everywhere. So I've implemented the "Document/View Model" whereby:
- There's a Windows Form, which we'll call "formView"
- There's a Class, which we'll call "classDocument"

Thus, when an instance of each the form and the class are instantiated, they
each will hold the same data, albeit be independent of each other.

To keep the two in perfect sync with each other, I've just wired up a
property of Document such that whenever its value is changed, this fires an
event that calls an EventHandler in formView. This works perfectly.

But my question is this: When an event occurs on the form (ex. a radio
button pressed, a checkbox checked, some text entered in a textbox, etc.)
what is the best approach to use to update the synched instance of
classDocument?

Two ideas come to mind:
1. Just write the data to the property
2. Wire up event handlers to update the property value

Or maybe there's an even better approach? Hoping someone out there can lend
me their expertise.

Thanks,

Robert Werner
Vancouver, BC
 
At first pass MFC Document/View is Model/ ViewController. The
ViewController owns the Model, responds to user and system input, calls
methods on the model, and updates the view. The Model knows nothing
about the view so it can be reused and can be tested as a stand alone
console
application. Pretty simple.

If you want to use registration/notification, consider the full
Model/View/
Controller. The Controller responds to user and system input and owns
the
Model and View. The View registers an interest in the Model through an
intermediary notification interface. The Controller calls methods on the
model
and can change the appearance of the View. When the state of the Model
changes, the View is notified through the intermediary interface, so
that the
Model knows nothing concrete about the View. The View then extracts data
from the Model.

Regards,
Jeff
 
Jeff,

Thanks for your input! I think for my current needs the first scenario is
sufficient. But I am encountering one problem that perhaps you have a simple
solution to. Hopefully I can explain this in simple terms:

Imagine having a form with a pair of radio buttons on it, one labeld 'Yes'
and the other labelled 'No'. They represent a Boolean value in The Model
(the instantiated class).

I wired up event handlers so that if the Boolean value is ever changed by
something other than the View (e.g. when the Model is populated from disk)
that the Yes/No radio buttons are set accordingly. That seems to work fine.

Then on the View I created a simple internal handler to deal with either the
Yes or No radio button being pressed. When this occurs the associated
Boolean value property in the Model is set accordingly.

But now I fear that I've created an endless loop! For example, if I press
the 'Yes' radio button then this in turn calls the internal handler, which
then sets the property value in the Model to "true". But then the code in
the Model, seeing the property being changed in turn calls the event handler
back on the form.

So:
- Is there in fact an endless loop occurring here?
- If so, what's the best way to resolve it?

Robert W.
 
Jeff,

Thanks for your input! I think for my current needs the first scenario is
sufficient. But I am encountering one problem that perhaps you have a simple
solution to. Hopefully I can explain this in simple terms:

Imagine having a form with a pair of radio buttons on it, one labeld 'Yes'
and the other labelled 'No'. They represent a Boolean value in The Model
(the instantiated class).

I wired up event handlers so that if the Boolean value is ever changed by
something other than the View (e.g. when the Model is populated from disk)
that the Yes/No radio buttons are set accordingly. That seems to work fine.

Then on the View I created a simple internal handler to deal with either the
Yes or No radio button being pressed. When this occurs the associated
Boolean value property in the Model is set accordingly.

But now I fear that I've created an endless loop! For example, if I press
the 'Yes' radio button then this in turn calls the internal handler, which
then sets the property value in the Model to "true". But then the code in
the Model, seeing the property being changed in turn calls the event handler
back on the form.

So:
- Is there in fact an endless loop occurring here?
- If so, what's the best way to resolve it?

Robert W.
 
But this is not the simple Model-ViewController. If you want to keep
this
simple the Controller owns the view and model. the controller responds
to
user input and calls the model and updates the view. You are done. If
you
want to use notification registration it gets more complicated.

The controller (radio button) should only fire an event if the state of
the radio
button changes so this should break any loops.

Regards,
Jeff
But now I fear that I've created an endless loop! For example, if I
press
the 'Yes' radio button then this in turn calls the internal handler,
which
then sets the property value in the Model to "true". But then the code
in
the Model, seeing the property being changed in turn calls the event
handler
back on the form.
 
But now I fear that I've created an endless loop! For example, if I press
the 'Yes' radio button then this in turn calls the internal handler, which
then sets the property value in the Model to "true". But then the code in
the Model, seeing the property being changed in turn calls the event handler
back on the form.

As Jeff has indicated, this kind of relationship cannot be resolved when you
only have a Model and a View.

This is why someone came up with the concept of MVC (Model View Controller)
and later with MVP (Model View Presenter), a more sophisticated and flexible
version of MVC

In MVC, the Controller acts as a Mediator between the Model and the View and
can ensure that, if a message comes from the View, that the resultant action
invoked on the Model does not cause infinite recursion.

MVP takes things further by splitting out the responsibilities for handling
changes even better.

I have had extensive practice in implementing an MVP framework using Delphi
which adds a couple more ideas to keep things better encapsulated than the
MVC.

The Model, not only holds an instance of the Value Type (the object to be
editied), but it also holds a Current Selection and a Command Set. Instead
of relying on a UI to maintain a selection, the Model is notified via an
Interactor when a user makes a Gesture in the UI; the Current Selection can
vary from being a sub-list in the case of a multi-item object to just the
single object in the case of a basic ValueType like a string or integer.

When the Selection changes, the Command Set is notified and changes itself
to only allow Commands that are viable for the given Selection. In the case
of a list of objects, if the Selection is empty, then the Add Command is
enabled but the Insert, Delete, Edit, Cut and Copy Commands are disabled.
Changing the Selection to a single item will enable all Commands, while a
multiple selection will disable Edit and Insert.

The Command Set can be visualised in the UI by a popup context menu or maybe
a MS Money style 'what to do' bar.

The View is made to be an Observer of the Value Type held in the Model and
will respond to changes in the Value Type by updating itself to reflect the
current state of the object it is displaying.

The Presenter, which holds a reference to each of the Model and View, also
holds one or more Interactors.

An Interactor is essentially an object that has one or more event handlers
or delegates that are listening for changes in the UI (View). The Interactor
responds to a Gesture, by interpreting it into : a change in the Selection
or a sending of change of content in the edit to the Value Type. This
includes UI elements like radio groups or checkboxes that are used to
represent sets or boolean values

UI elements like buttons and menu items are not usually handled by an
Interactor, but are linked directly to a relevant Command; the OnClick event
handled directly in the associated Command and the button or menu item
enabled or disabled according to the state of the Command.

Now comes the bit that keeps the Model and View apart in terms of stopping
recursion.

Interactors can be enabled or disabled; they can enable or disable
themselves. Which means that if they instigate a change in the Value Type
that is known to propogate to a change in the UI, the Interactor can prevent
itself from receiving further notifications until the change has completed.

Interactors can also be nested and can propogate user input to other, more
sophisticated, Interactors to handle things like dragging an item from one
control to another or even to another application.

Ultimately, the MVP framework allows for the nesting of MVP 'Components' so
that each property of an object has its own MVP to link it to an
edit/checkbox/combo on a form and these are all contained and maintained
within an overall Presenter which links the object in the Model to the form.

Once the nested MVP framework is completed, it is then possible to write a
business class and design a form where each edit has the name of the
property it is to represent, but where there is absolutely no code on the
form itself. Then by simply instantiating a Presenter, passing the business
object to the constructor, a Model will be created for you, a View (form)
will be created for you, they will be linked together, all the properties
will have MVPs created for them and linked to the controls on the form via
Interactors; and finally the form will be shown and managed by the
Presenter.

Regardless of whether you want to achieve this level of sophistication in
your current situation, you at least need to implement some kind of
Controller to act as a Mediator between your Model and View, taking into
account the idea of enabling and disabling used in my Interactor classes.

If you are interested in further reading on MVP, then I have some articles
on my website www.carterconsulting.org.uk, or you can Google in the news
groups for "joanna carter interactor" for more discussion on the finer
points on this part of the MVP which are not covered in the articles.

Joanna
 
Joanna, wow, quite a bit of detail there! Definitely very overwhelming for
me on my first real C# project. But I am checking out your site now and will
read more about MVP frameworks generally. Thank you so much!

Just ake the idea of a simple Mediator class like the Controller you will
find in MVC, and use that to solve your immediate problem, but then you can
build up slowly to greater things :-))

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 
Back
Top