views:

171

answers:

5

I have a Person class in the Model and want to assign 15 of its attributes to labels in the View. The View shouldn't access the Model. That means the Controller will handle creating the Person. How does the View get these Person attributes from the Controller? If the Controller contains a member of Type Person, the View can do something like:

lblFirstName.Text = theController.Person.FirstName;

lblLastName.Text = theController.Person.LastName;

lblCity.Text = theController.Person.City;

However, the View is still directly accessing the Model (ie, Person). The Controller could have its own Person class, copy all of the Model's Person attributes into it and have the View use syntax as above. But there's much duplication in that design. Any suggestions?

A: 

The person could be in the view-data. I don't personally think that there is a huge issue with the view accessing instances of model types that the controller has already obtained, so personally I would let the view see the Person directly.

It might be desirable to flatten the model into a view-model if there are lots of deep properties required, such as person.Foo.Bar.Blip to obj.Blip in the view-model.

If you are dealing with a single object, another option is to place each value separately into the dictionary - but this is a bit messy.

Another option is an abuse of anonymous types; but don't do this! I won't even repeat the details here, it is that grotty; but here t'is.

Marc Gravell
A: 

You can separate the concerns in your Model even deeply if you use DTO classes which are objects with properties or to be more strict a constructor and a bunch of readonly properties. At first it might seems like duplicating code but it becomes a really flexible way to handle differernt kind of views and results expected from your model.

Perpetualcoder
Leaning towards this...
rball
A: 

I'm not sure why you can't share your model in your view. There's no need for duplication and it doesn't seem that you need to use a DTO so I'd just pass across the Person in the state bag and you'd be good.

I think you are thinking more about your services. You don't want your view accessing your services, but your controller would do that package it up and then send to the view. As far as just the simple model though there's really no draw back to sending that over IMHO. The only other way would be to have a Model in the same project as your view that would essentially be the copy of your model except only with values that you are sending across. In that case I could see the benefit, but again...your example isn't that specialized.

rball
A: 

This is in a winform by the way. The model is a seperate project/DLL also. What is DTO?

The Person attributes in the Model have special logic, which I didn't want the View running into problems with. For example, the View might do:

string fn = myController.Firstname;

And get an exception thrown because of logic in the FirstName property. So, the Controller light weight (duplicate) version of the Person object wouldn't have any of those issues, since its properties are only strings.

Also note that your View will need a reference to the Model to handle the hidden Person property coming from the Controller. I don't like it.

4thSpace
This is not an answer. Please edit your original question with the additional data.
Sunny
DTO = Data Transfer Object
Harry
Sorry, my model actually contains no logic at all. It simply has the properties that declare the model. Within my model project I also have interfaces to my service classes so there's pretty low friction there. I have all the "special logic" in my service project contained within services...
rball
...having said that I have discussed with a few coder friends and we're starting to lean towards having the duplication, if for anything having a DTO that would allow us to have a cleaner view. For instance, I noticed for dates I would be doing things in my View like...
rball
thread.Message.DatePosted.ToShortDate(); instead if I had a seperate DTO that still pulled used the model but placed the data within the DTO instead and then pass that across to the view: message.DatePosted.
rball
I think where we differ though is you have logic in your Model and I don't. I have this abstracted to another layer.
rball
+2  A: 

Slightly off topic (on MVC) but on topic about your issue:

Why not use a less cumbersome solution? If you need to simply assign to 15 labels 15 values you could give your controller an indexed property or method that uses your Label object's design time name as key to retrieve the appropriate value from your model using a dictionary or reflection on your entity property names or a big switch statement:

foreach(Control control in myLabelsPanel.Controls)
{
    Label label = control as Label;
    if(label != null)
    {
        label.Text = myController.TextForKey[label.Name];
    }
}

Edit: I just forgot to add that I dot't see as a bad thing the view accessing my model entity classes. After all, they are the model and they can become part of the ViewModel (if you are using that paradigm), and MVC encourages the View knowing about the model (bue not the other way around).

Sergio Acosta