Should a user control have its own view model?

20,752

Solution 1

This is not a yes or no question. It depends on whether having extra view models affords you better maintainability or testability. There's no point adding view models if it doesn't gain you anything. You'll need to gauge whether the overhead is worth it to your particular use case.

Solution 2

I would say that each user control should have its own ViewModel, because that would allow you to reuse the ViewModel/UserControl pair in new constellations in the future.

As I understand it, your window is a Composite of user controls, so you can always create a ViewModel that composes all the separate ViewModels for each of the user controls. This will give you the best of both worlds.

Solution 3

[should] each user control have its own ViewModel or should the window as a whole have only one ViewModel?

Unfortunately, the highest-voted answer to this question is misleading, and based on comments I've exchanged in other questions, providing poor guidance to people trying to learn WPF. That answer replies:

Your UserControls should NOT have ViewModels designed specifically for them.

The problem is, that's not the question that was asked.

I would agree with the general sentiment that when you write a UserControl, the public API of the control should not involve creating also a view model type that is specifically designed to be used for that control. The client code must be able to use whatever view model it wants.

But, that does not preclude the idea that "each user control [might] have its own ViewMomdel". There are at least two obvious scenarios I can think of where the answer to that would be "yes, a view model for each user control":

  1. The user control is part of a data template in an items presenter (e.g. ItemsControl). In this case, the view model will correspond to each individual data element, and there will be a one-to-one correspondence between the view model object and the user control that presents that view model object.

    In this scenario, the view model object is not "designed specifically for them" (so no contradiction with the questionable answer), but it certainly is the case that each user control has its own view model (making the answer to the actual question "yes, each user control may have its own view model").

  2. The user control's implementation benefits from, or even requires, a view model data structure specifically designed for the user control. This view model data structure would not be exposed to the client code; it's an implementation detail, and as such would be hidden from the client code using the user control. But, that certainly still would be a view model data structure "designed specifically for" that user control.

    This scenario is clearly not problematic at all, which directly contradicts the claim that "Your UserControls should NOT have ViewModels designed specifically for them."

Now, I don't believe it was ever the intent of the author of that answer to rule out either of these scenarios. But the problem is, people who are trying to learn WPF may not have enough context to recognize the difference, and thus may incorrectly generalize with respect to user controls and view models, based on this emphatic, highly-upvoted, and misleading answer.

It is my hope that by presenting this alternative view point as a point of clarification, and answering the original question in a less narrow-viewed way, those who found this question while learning more about WPF will have better context, and a better idea and when a view model might be implemented specific to a user control and when it should not be.

Solution 4

I guess your application is doing some sort of view composition, so if you make your user controls to have its own view model, you'll have more freedom to embed them in other host windows without changing the window global view model.

As an added bonus, your application will be more suited to evolve to a more architecturally-sound composition model as that provided by Prism or Caliburn frameworks, if the application requirements arise.

Solution 5

I'd be inclined toward a viewmodel.

Bear in mind that all of these patterns are designed to fragment your code to make it more maintainable in the future. Including MVVM. The view has certain responsibilities, so too the viewmodel, so too the model. A fresh developer can come in, can recognise this pattern, will have a better idea where to find and maintain things. Better than if it were a heap of spaghetti.

So, within that, if you have logic which correctly pertains to the usercontrol, which correctly belongs in the vm, then why not?

But there is a caveat here. Bear in mind what a UserControl is. It's something that is a tiny snippet of UI that can be reused from place to place. Your vm should be the same - reusable. The last thing you want to end up with is a vm which behaves one way in one scenario, and a different way in another scenario.

Note, no technology talked. I'm just talking about the logical structure of the pattern.

Share:
20,752
AwkwardCoder
Author by

AwkwardCoder

Updated on November 25, 2021

Comments

  • AwkwardCoder
    AwkwardCoder over 2 years

    I have a window made up of several user controls and was wondering whether each user control have its own view model or should the window as a whole have only one view model?

  • Lynn Crumbling
    Lynn Crumbling about 9 years
    Your answer contrasts heavily with @Will's answer. His seems to make more sense: usercontrols are still just essentially controls. I'm curious if you've changed your opinion since '09 when you wrote this answer.
  • Lynn Crumbling
    Lynn Crumbling about 9 years
    Your answer contrasts heavily with @Will's answer. His seems to make more sense: usercontrols are still just essentially controls. I'm curious if you've changed your opinion since '09 when you wrote this answer.
  • James B
    James B almost 9 years
    Will seems pretty adamant, but I err on Mark's side. To me there is no reason why a control can't have its own view model: you just have have to appreciate that they exist as a coupled pair. We bind views to view models all the time and pragmatically speaking a one-to-one relationship exists between a view and its view model (one to many for a view model and model). For simple views that just present data do it in the code behind. If there is logic involved, why not do it in a View Model so you can do some all important unit testing.
  • James B
    James B almost 9 years
    Think testing. If your control has some complex logic, why not stick it in a ViewModel and test it.
  • Étienne Laneville
    Étienne Laneville over 4 years
    In scenario 2, if you have a ViewModel created specifically for a user control and wish to hide it from the client, how do you set it as the DataContext for the User Control? You don't want that happening in the XAML because it would be up to the client to add it when using your control. You don't want to do this.DataContext = this; // omfg (stupid stuff according to the popular answer you refer to) either.
  • Peter Duniho
    Peter Duniho over 4 years
    @ÉtienneLaneville: "how do you set it as the DataContext for the User Control?" -- you don't. You should not modify the top-level UserControl.DataContext property, as that's the property the client code can see and likely will want to modify. Instead, you would want to set the DataContext property of some element inside the UserControl. The UserControl will necessarily have a single top-level element as its content (e.g. StackPanel, Grid, whatever), and that would be a fine element on which to set the DataContext. Alternatively, one or more child elements inside that.
  • Étienne Laneville
    Étienne Laneville over 4 years
    I see, so instead of something like <local:UserControl.DataContext> <local:ViewModel Value="1" /></local:UserControl.DataContext> when creating the user-control in your Window, you would add it around the controls that need it, within your User Control: <Button Content="{Binding Path=Value}" Command="{Binding Path=IncrementValueCommand}"> <Button.DataContext> <local:ViewModel Value="1" /> </Button.DataContext> </Button>
  • Peter Duniho
    Peter Duniho over 4 years
    @ÉtienneLaneville: yes, that's right. Ideally, there'd be a container element where it's natural to add one view model object that can apply to the entire user control. But there will always be exceptions, where one might want/need to provide an element-specific view model to e.g. a Button or something. To be clear: once we accept that the UserControl.DataContext property is off-limits, we're pretty much back to the question asked here, and of course that means being open to either possibility: a single view model for the entire component or element-specific view model objects.
  • Étienne Laneville
    Étienne Laneville over 4 years
    @PeterDunhino if we set the DataContext of a UserControl to our View Model and the client then sets it something else, that clears out our ViewModel then? That's why you would add it to the top internal element inside the UserControl instead, where it will override the new DataContext?
  • Peter Duniho
    Peter Duniho over 4 years
    @ÉtienneLaneville: "that clears out our ViewModel then" -- yes, the DataContext property can only reference one object at a time. "where it will override the new DataContext" -- again, yes...note that the client code's view model is there solely for binding to your user control's public dependency properties. So you don't need it as a context within the user control implementation itself. Overriding the context in a child element is fine in that case.