.NET Framework - pass object from model to view in event

Asked By mp on 18-Jan-11 12:24 AM
amazing, i think this is working!!!

this is the output from some debug.print lines to trace action:

view creates presenter
presenter creates model
presenter asks model to subscribe to presenter's events
model subscribes to presenter events
presenter subscribes to models GotCriteriaDictionary event
presenter subscribes to view's events
view subscribe to presenter's GotCriteriaDictionary event
view raises event GetCriteriaDictionary
presenter catch event from view GetCriteriaDictionary
presenter raise event to model GetCriteriaDictionary
model catches event from presenter GetCriteriaDictionary
model gets data into sortedDictionary to pass back upstream
model raise event GotCriteriaDictionary and pass back CriteriaDictionary in
eventargs object
presenter catches event from model and raises event to view
view catches event from presenter and gets dictionary from event arg
view inserts dictionary into listview

does this look approximately right?
it appears to work...amazingly enough...
thanks to Peter and Jeff's collective patience :-)

i was not sure about the last item
view inserts dictionary into listview

is that too much responsibility inside the view?
should presenter be filling the listview instead?
ie view exposes listview property which presenter fills?

thanks
mark




Peter Duniho replied to mp on 18-Jan-11 10:42 AM
It looks plausible.  Whether that is "right" or not depends on more
information than I have.  In isolation, there are at least a couple of
things that stand out:

??? The debug output mentions subscribing to "GotCriteriaDictionary",
but not "GetCriteriaDictionary", yet the latter is the event mentioned
most often in terms of activity.

??? It seems like there may be an over-reliance on events as a way of
object interaction.  it is possible that it makes sense for the view to
raise an event saying that it needs data, but it seems odd to me that
the model would have to subscribe to such an event, rather than the
presenter simply retrieving the necessary data from the model.  And the
event from the view makes sense to me only if the need for data comes
from some user interaction.  Otherwise, at the very least the presenter
could just be initializing the view imperatively, and it is not
unreasonable to have a design where the view retrieves the data directly
via the model interface, or some more abstract wrapper around the model
interface.

Having the model subscribe to an event that is raised when the view
wants data seems awkward at best, and at worst ties the model to the
view implementation in undesirable ways.  The model data structure
should be completely agnostic regarding how the view is implemented, and
having it subscribe to an event in the presenter that simply mirrors a
similar event in the view does not seem right to me.

Now, different people have different ways of thinking about all this,
and at the end of the day, if it works, it seems understandable, and the
design fulfills whatever specific "separation of concerns" goals you
might have, I am not going to say it is outright wrong.  But for me, I
probably would not do it that way.

I also will point out that in the .NET jargon, we usually talk of

Finally, if you do decide that this chained event design is best, you
may find that rather than having two different events, one to request
data and one to provide it, it makes more sense to just allow the event
handler to pass back the data in the event data structure by setting a
property before returning.  There is some precedent for this sort of
design, such as the CancelEventArgs class, and it could be a simpler way
to manage the data flow you are dealing with (but again, IMHO using
events for this particular functionality is not best in the first place).


IMHO, the presenter definitely should not need to know about the
ListView type.  Whatever else you do, the view interface should
completely abstract the actual view implementation.  When you design the
interface, make sure that you think about whether that interface could
work just as well for a view implemented in some other API, such as
using a console application, web client, or WPF instead of the Forms
API.  If you note a dependency on the Forms API that would not be
immediately replicable without having the Forms DLL referenced, then the
interface is leaking implementation.

Pete
mp replied to Peter Duniho on 18-Jan-11 06:15 PM
apparently my enthusiasm was premature.
how do you get that damned cork back into the champagne bottle? :-)


i've gotten so caught up in trying to learn *how* to raise events
I guess i misunderstood what I was reading/hearing about *why*
I thought that was what i was being suggested to do, by the mvp info and
other previous 'conversations' like the push / pull analogy.


it is possible that it makes sense for the view to

i thought the presenter *was* retrieving the necessary data from the model,
by raising the event to which the model responded.
It would have been a heck of a lot easier to just read a property on the
model,
but I guess i misunderstood, thinking that was too much coupling,
and that events were somehow separating the players more???


And the

in the future there will be some buttons requesting various actions/data
i've been trying to learn *how* to pass events back and forth for that.
in this first case, the event is called in the OnLoad sub.


Otherwise, at the very least the presenter

again, i guess i'm misunderstanding a lot about the whole background
of how things are "supposed" to be put together <g>(i know, there is no one


like i said, obviously i'm just being dumb as a box of rocks here.
I thought that is what "everyone" has been "suggesting"
for the view to be "dumb" - which i took to mean - it only raised events...
like when a button is pushed, or when it loads and needs to fill some
control with data
to request information, but not know where the info lived or how to get to
it>?????

so I have a form.
the form has a listview.
I want to put some items in the listview
the items are at the moment living in a spreadsheet on disk.

how "should" i be doing that?
(recognizing that there are different ways, but in your opinion, how would
you handle that?)




[...]

thanks again, and sorry for being so dense.,
mark
Steel replied to mp on 18-Jan-11 08:16 PM
Of course you can roll your own view and presenter, because that is the
beauty of MVP.

The control is with the presenter and not the view. The IView is just
the Interface between the UI and the Presenter. The only events you
should be raising are events on the IView that points to a method on the
Presenter.

The Presenter should get/set any controls from the IView work with them
and getting/passing them back on the Interface, or the presenter should
be getting/setting an object if you are using an object or object graph.

It looks like you have lost focus, and you are raising events like
rabbits. :)

Did that tutorial show you any of what you have gone off and done?

You just should have kept it simple. I going to say it. That's the
problem with developers. They want to go complicated, when they should
have just kept it simple. Simpler is better. it is as simple as that.

Mind you, there is noting wrong with being complicated when it is
required. But the UI, IView, Presenter are not it.

I say you need to go back to square one with the tutorial, and what you
are doing, keep it simple -- follow the tutorial.
mp replied to Steel on 18-Jan-11 11:07 PM
yep, it is what i started with
the view creates the presenter and raises an event to the presenter
that is what i'm doing
then the presenter called a method on the model
that is where i went wrong...using an event instead

when the tutorial stopped at "fake getting product"
i went on and tried to do what my app needed to do
not in the right way evidently, but...


i'll go back and review again,

so it is usually just the  view that communicate via events?
the presenter just calls methods on the model and sets properties on the
view?

thanks
mark
Peter Duniho replied to mp on 19-Jan-11 03:34 AM
I agree that you misunderstood.  :)  Events abstract things that
just as tightly as by other class members.  The coupling is determined
by what types are shared, and how much one class depends on the specific
interface and implementation of another.  Adding events does not help
reduce coupling, it is just a different way to look at how object interact.


Well, there is a "supposed to", but it is more of a higher level goal
than focusing on specific implementation details.

In any case, it seems to me that again, it is important to stay focused
and not try to learn too many things at once.  Frankly, a lot of the
higher-level design techniques just do not make as much sense until
you have seen enough of the lower-level implementation details.

it is a bit like "kndg" posting the explicit "listener/observer" pattern
implementation.  it is not that you would  write code like that in C#, but it
_is_ useful to understand the more explicit way to implement those kinds
of patterns before using language features that abstract and hide
implementation details for those patterns.

As far as the question of events go, it is useful to understand the
difference between polling and interrupt- (or event-) driven
programming.  Start with the fundamental goal: you want to know when the
state of something changes.  This could be a value changing, or the user
performing an action, or some data arriving, or whatever.

There are two basic ways to accomplish that goal: keep checking the
state to see if it is changed since the last time you looked; or register
yourself in some way so that the thing controlling the state can just
let you know when it happens.

This distinction has existed essentially since the beginning of
computers in one form or another, but it usually comes down to the same
basic issue: checking (or "polling") is wasteful, while waiting for an
interrupt costs nothing but a little bit of memory to store the
notification target.

In C#, this distinction roughly comes down to some code repeatedly
examining the state of some other object's property, or subscribing to
an event and "waiting" for the event to be raised (where by "waiting" I
simply mean that the code to handle the event is not executed until the
event is raised; it is not like the object is literally sitting there
actively waiting???after all, that is the whole point of interrupt-driven
programming).

So, when thinking about how to design your code, the question mostly
becomes one of how the information needs to move between objects.  In
general, there is no reason to use an event unless it is something that
the code that is interested in it will not already know it is time to access
that something.

For example: the presenter has no way to automatically know when the
user's interacted with the view object.  It _could_ just keep looking
for some state to change in the view object, but that is wasteful.  So
instead, an event is appropriate.

On the other hand, once that event is raised, the rest of the logic is
completely deterministic and sequential.  The presenter knows that it
needs to retrieve some data from the model, and then pass it to the view
(possibly reformatting it to suit the view's needs).  There is nothing in
that flow of data that would require any of the actors to wait for
something to happen or otherwise repeatedly poll; it knows it can get
everything it needs on the first try, and so it simply should.


That's a completely different question from the one of whether to use an
event or not.  it is true that _each_ of the objects in the design
pattern should be "dumb".  The less any one object knows about any other
object, the better.  Encapsulation, information hiding, etc. these all
relate to isolating functionality and having well-defined ways for what
information is shared to flow between objects.

it is kind of like your brain.  Our biology _could_ have been implemented
such that we had no division of hemispheres, with everything in the
brain connected to everything else.  And granted, science is still
learning the whys and wherefores about why the brain is organized the
way it is.  But I think it is safe to assume that the division of labor,
with specific links between areas (such as the corpus callossum that
connects the hemispheres) is an important feature that helps the brain
work more efficiently and, probably more importantly, helps the brain
evolve and _develop_ in a more efficient way.

Likewise, in your program, you _could_ make everything in every class
public, and just have one type fiddle directly with whatever's in the
other type, with each type having intimate knowledge of the
implementation details of every other type.  But to maintain such a
program means that you have to remember how _everything_ works all at
once, because no matter what part of the program you are working on, you
cannot afford to not know how changes to it might affect other parts of
the program.

But if you keep things isolated, and require each part of the program to
expose their features in ways that are well-defined and change very
little, you have the freedom to modify the internal implementation
details without disturbing the other parts of the code.

All of that is important.  But it has little or nothing to do with
whether some feature is to be exposed as an event or not.


A ListView control is just that: a view of a list.  So fundamentally,
you need for the presenter to deliver a list of data to it.  The first
question is what data will actually be in the list.  Then your view
needs to have some kind of mechanism that the controller can use to
deliver that data to it.

If you expect the data to flow only into the view, to be shown to the
user, then passing a list from the controller to the view is probably
best.  If the list data will flow both ways, then it is possible you will
prefer a property.  If you want to get really fancy, then you can
abstract the ListView object as an interface that allows list-like
operations, perhaps even as an IList<T>.  Then your IList<T>
implementation can update the ListView directly as the controller
modifies it, and retrieve data directly from the ListView if the
controller tries to get things from the IList<T>.

Of course, you also need some data type that represents a single item in
the list.  This might as simple as a string, or it could be a more
complex data type.  It just depends on what you are using the ListView to
show the user.

However, you do it, the important thing is that the controller should
not have any need to know about the ListView type, nor even that a
ListView object is being used to present the data to the user.

Hope that helps!
Pete
Big Steel replied to mp on 19-Jan-11 04:48 AM
on the

The UI/form communicates with the Presenter  by raising an event on
the IView, the IView event will access a method on the Presenter, and
the Presenter will access a method on the Model/BLL.

A control, object, object graph or primitive data type will be
represented on the IView, which is shared between the UI and
Presenter to pass things in either direction using get/set.

That's it keep it simple.

--
posted with a Droid
mp replied to Peter Duniho on 19-Jan-11 10:20 AM
no, no, as we have seen it is nothing like *my* brain

[...]

thank you very much
i'm going to read and re-read and re-read that
mark
mp replied to Big Steel on 19-Jan-11 10:21 AM
thanks Steel,
that is for sure a problem for me, learning to keep it simple
mark
Big Steel replied to mp on 19-Jan-11 11:51 AM
I am creating a Web based MVP demo project for a presentation of MVP.

It will doing everything the tutorial is doing, but it will not be
using events in the IView. I may post some code when I am done.

It will be based off of this.

http://www.codeguru.com/csharp/csharp/net30/article.php/c15489__2/ADONE
T-Entity-Framework-Tutorial-and-Basics.htm

--
posted with a Droid