10

So I've check this post and a couple of others that discuss similar situations, but still haven't found the best solution to the problem I'm trying to solve.

In my mvvm application each view has one viewmodel. I want to make the viewmodels as flat as possible, but it doesn't seem to be practical when it comes to binding with observable collections. For example, If I have a page that displays a client's profile information, and one of the fields is a group of checkboxs for active subscriptions. I would have a viewmodel that looks like this:

public class ClientViewModel
{
    public class SubscriptionViewModel
    {
        public SubscriptionModel Subscription {get;set;}
        public bool IsChecked {get;set;}
    }

    public string Name {get;set;}
    public string Email {get;set;}
    ...
    public ObservableCollection<SubscriptionViewModel> Subscriptions {get;set;}
}

Because of the extra IsChecked property that is not part of SubscriptionModel, I have to create a separate SubscriptionViewModel and nest it inside the client. What would be a better alternative way to do this so that I don't have to end up with viewmodels inside viewmodels?

Community
  • 1
  • 1
nemesis
  • 253
  • 1
  • 4
  • 11

1 Answers1

10

For me it's perfectly fine to compose VM out of several others. I'm doing this quite a lot. Sometimes due to the need to re-use parts, sometimes just to have a better readability in the code. Every VM has still a corresponding view. So there is a view for the "inner-viewmodel" as well as a view for the "composed-viewmodel".

I would not use nested public classes though. I'm treating them as "first-class-citizen".

The scenario I've recently had, was a small product information display on a customer page as well as the invoice page. So I decided to create a ProductOverviewViewModel as well as a ProductionOverviewView, and both are used within the customer and invoice views/viewmodels.

Martin Moser
  • 6,219
  • 1
  • 27
  • 41
  • thank you! one question though on the "first class citizen". if the nested class is not public, the properties will also not be public. doesn't this mean that I won't be able to bind to the properties? – nemesis Feb 19 '15 at 14:45
  • 1
    I would simply not use any nested classes. They are both viewmodel/views. The inner-view is far more than an internal helper class, therefore it should be structured in the code the same way. – Martin Moser Feb 19 '15 at 14:58
  • i see.. I agree that it would make sense to put all viewmodels in the same area the same way, but in this particular case the inner view is indeed only an internal helper class. the only reason I need the extra viewmodel is to add the additional `IsChecked` property to the model, and I can't do that directly in the model itself because it violates the separation of data and view. apart from that, the inner viewmodel doesn't contain any logic – nemesis Feb 19 '15 at 15:24
  • What if you make a change in one of your 'parent' view models because it's required for one specific view? Now all other views will be unintentionally affected because you re-use the view models? – BornToCode Dec 16 '15 at 17:51
  • @nemesis seems like your choice of terminology has stumped you, if you simply rename your field to `IsConsented` or something like that is is the notion of the user's action rather than the specific's of the View mechanics then you are freed from those shackles. – straya Jan 25 '22 at 01:03