views:

486

answers:

4

Hi,

as far as I understand the ViewModel should abstract the model from the view and add additional logic to handle the presentation stuff.

My question is:

How would I create a dataform that is suppose to handle user input for an order and details at once. It should present fields for entering the orders as well as the fields for 1 detail.

My Model would have an object for an order which contains a list of OrderDetails.

How would look my ViewModel for my OrderEntryForm like?

Would I have an OrderViewModel and an OrderDetailViewModel and my my OrderEntryForm would contain a property of OrderViewModel and one for OrderDetailViewModel? (nesting ViewModels?) How would validation be handled in this case? Since Validation should go close to the model? Especially when I work with RIA-Service... Wouldn't it make more sense to put it in the ViewModel?

How far would you abstract the Model from the ViewModel? Example:

 private DateTime _OrderDate;
        public DateTime OrderDate
        {
            get { return _OrderDate; }
            set
            {
                if (_OrderDate != value)
                {
                    _OrderDate = value;
                    OnPropertyChanged("OrderDate");
                }
            }
        }

this would mean I have to map the ViewModel-Property to Model-Properties. Cannot leverage Validation-Logic from the Model here...

This example:

 public DateTime OrderDate
        {
            get { return Model.OrderDate; }
            set
            {
                if (Model.OrderDate != value)
                {
                    Model.OrderDate = value;
                    OnPropertyChanged("OrderDate");
                }
            }
        }

would requiere to pass in a Model. Have the access to the validation logic of the model but also a coupling...

Most examples on the web show dataforms which use ViewModel's that a just a representation of the tables not a real abstraction...

I know and I saw this

stackoverflow.com/questions/744474/combining-net-ria-services-and-mvvm-in-silverlight-3-0

I also read nikhils blogpost on this but this handles also only Products straight mapping from the tables of the database... =(

I know alot of questions...

What are your opinions on that topic? How would you handle complex dataforms?

A: 

To clarify, the VM is an abstraction of the Model, not of the View and not the other way around.

You can certainly use multiple VMs to correspond to discrete portions of your View. If you're not going to need separate VMs for Order and Details, you can just have an OrderAndDetialsViewModel that contains everything, and the whole View will bind straight to that. This is where the abstraction comes in.

You are right, that your model's validation logic is going to be distinct from your ViewModel's validation logic, if you put any in there. In no case will the validation be in the View.

I'm not sure I follow your second example. What is the Model object? Your VM may know about the Model(s) from which it is composed, but it is not going to expose it/them as such directly to the View.

I hope this helps somewhat. Please let me know if there is any part of your post that I failed to address.

Jay
The 2nd option would mean either a typed ViewModel<T> or a contructor which receives a the Model
silverfighter
i think your statement "the VM is an abstraction of the Model, not the view" is misleading/confusing. the view model is essentially a model ("abstraction") OF the view. It's not a model FOR the view. check fowlers Presentation Model pattern
Schneider
A: 

Chris,

I have had the same issue and end up implementing it in a crappy way :-( (two vieModels one per view, but passing the parent to the child View... bad stuff).

From my error I learn that next time I would give a try to:

  • Generate a single ViewModel, but in the child view pass a detail entity in the datacontext (this detail entity does not have to match with the proxy generated entities, maybe is a container of that entities).

  • Generate a singleton controller class: this class won't be exposed to the view, it will be transparent for the view, just the detail view model will ask the controller for that dependant data instead of going to the DAL.

    Not sure if this are going to be clean solutions, have to give a try and fail :).

    I agree with you... there are not real samples with this kind of scenarios.

    What do you think?

    Thanks Braulio

    PS: About validation, if we create our own super entities, we can there define our validation, in my case I have tried as well extending the entities using partial cases and then I can have an entity myPhoneNumberDetail with my special validation.

Braulio
A: 

I personally think there are no hard and fast rules... well, there is one - be pragmatic.

Pragmatically speaking, a view model is a model, and so is a data model. Both are classes, independent of the UI, and surface state as properties, operations as methods, and notifications as events. The thing that I think in my mind differentiates them is how general they are. I see a model as generally usable across multiple views, vs. a view model optimized for a particular view.

I would personally never abstract for the sake of abstracting. I would never surface top-level properties for every model property and implement it by delegating to an underlying model. This increases work. It increases the amount of code to be tested. It requires propagation of metadata, change notifications etc. If there is some actual logic to add, then yes, there would be properties on the view model I'd expose and delegate to the underlying model as appropriate. Even there I'd ask if it is reasonable/appropriate to expose those as computed properties on the model (view model and data model are both models).

As far as surfacing DAL types directly vs. not, that in my mind is somewhat orthogonal. It depends on other factors - how much do you want to abstract the DAL, how useful a DAL type is - for example, if a DAL type has a lot of foreign keys, a presentation model equivalent or projection might be more useful where there is some denormalization done. Sometimes security might be the reason to write a presentation model/projection - eg. I don't want to send email addresses to the client, and instead want an alternate representation of email addresses.

In my sample, I used a DAL type directly, to simplify and not have an overload of concepts in a single sample. I do want to blog about presentation models and projections in a dedicated manner... and so didn't want to mix posts of viewmodel and .net ria services with presentation model concepts at the same time.

NikhilK
A: 

As is so often, with patterns, it really depends. The ViewModel can expose the underlying model, and there is no hard and fast rule that says you "must" hide everything and delegate. I have spoken to many folks that are strict adherents to LOD and still they agree that in the case of UI binding, it does not apply.

Now in the case of whether that model is a DTO or not there you will find a lot of differing opinions. Some believe that the only thing that should ever be on the client is a pure projection i.e. a DTO with all logic living on the server, while others believe that that moving entities between the tiers is fine. That would be an discussion for a different post. :-)

In general the guideline that i would recommend is always at least have a high-level VM which can be used for screen state, etc.

As far as child models, like OrderDetail, then if the child model is sufficent to just bind to then just expose it directly. Now one thing to consider is around notification, if you model is not implementing INPC than you may have no choice but to wrap it in order for binding to properly work.

Even if it implements INPC there may be view-specific concerns that that model does not contain, but which are required to for the view to function. In that case I would use simple aggregation and create an OrderDetailVM that directly exposes the underlying OrderDetail and adds additional properties.

For example

public class OrderDetailViewModel
{
  public OrderDetail OrderDetail {get;set;}
  public bool IsValid {get;set;}  
}

Where IsValid is checking some screen-specific logic.

It really depends though on how much encapsulation you want to achieve. I wouldn't find anything wrong with using a delegation model. Depending on the complexity though it might get unwieldy, for example imagine if OrderDetail had additional children, etc.

HTH Glenn

Glenn Block
A glossary might be useful here: LOD, DTO, VM, INPC! I've been looking up acronyms on google for the last 5 minutes ;)
Groky