0

I'm still not totally sure what constitutes a view model. I have a class that I use to wrap my model and alter the data slightly, but I am not sure whether it constitutes a view model. What is necessary to be considered a view model? Is it merely not supposed to have direct dependencies on the view, so that the viewmodel does not know how the view uses its properties and the view does not know what is in the viewmodel? and when the view wants to update anything it just gives some abstract command that the viewmodel takes and uses to update the model?

As I understand it in MVVM, I'm supposed to use properties on the view that bind to properties on the viewmodel that bind to properties on the model.

and in the reverse direction, I'm supposed to use commands from the view to the viewmodel, which then can either uses Icommand to command the model, or can just call public functions in the model to make changes to it.

One confusing thing is that in the example of MVVM that I saw made it seem like in MVVM the view should have no code behind other than perhaps creating commands, but I don't see how I could do that in my current project. I'm making a custom control using lots of controls that are interacting on events.

how would I make one treeview expand on another treeview's expand without using events?

Jon
  • 428,835
  • 81
  • 738
  • 806
James Joshua Street
  • 3,259
  • 10
  • 42
  • 80

2 Answers2

2

Often, View Models end up being very similar to your domain models. One of the main goals of having View Models is to separate the GUI development from the business logic. For example, let's say you have a "User" domain model that has an IsAdmin property which you don't want exposed to the View. You create a View Model called "UserViewModel" that still has the ID, Username, and Password (see example code below), but doesn't have an IsAdmin property. Another approach is to use the domain model inside your view model, see the "AlternateUserViewModel" class below. There are pros and cons to any View Model solution. Creating the UserViewModel class with properties means you are essentially duplicating the objects you created for the domain model, since often times your domain models will be very similar to your view models. With the AlternateUserViewModel approach, there's not clear separation between your business logic layer and your GUI layer because the view model still needs to "know" about the domain model. What approach you decide on really depends on the environment you're working in. For personal projects, I like using the 2nd approach because separating the business logic from the design layer isn't such a major concern that I wouldn't want to let the view model layer "see" the domain model layer, but for a large corporation where you have separate teams working on the design layer and the back-end, the first approach may be preferred.

public class User
{
    public int ID { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public bool IsAdmin { get; set; }
}

public class UserViewModel
{
    public int ID { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

public class AlternateUserViewModel
{
    public User User { get; set; }

    public User ToDomainModel()
    {
        if (User == null)
            return null;

        // if this is an existing user, retrieve it from the database so you're not overwriting the IsAdmin property
        if (User.ID != default(int))
        {
            User existingUser = UserService.GetUserByID(User.ID);
            existingUser.Username = User.Username;
            existingUser.Password = User.Password;
            // IsAdmin is not set because you don't want that property exposed in the View Model
            return existingUser;
        }
        else
        {
            return new User
                       {
                           Username = User.Username,
                           Password = User.Password,
                           IsAdmin = false
                       };
        }
    }
}
Peter Pompeii
  • 1,415
  • 1
  • 14
  • 16
1

You have a number of questions here (consider breaking it into multiple posts). I'll try to answer some.

I think of ViewModel as THE app, in other words, this is where most of the app's logic happens.

In other words, ViewModel receives an input of:

  • Commands from the View
  • Changes in bound properties from the View
  • Events from a background service (e.g. when data is received from the Web)
  • Other events from the system or from domain models

and generates an output of:

  • changing properties that the View would bind to (e.g. IsBusy that could cause the View to display the waiting indicator)
  • showing/hiding stuff in the View (indirectly, of course, for example using various bool Properties)
  • causing navigation to other Views (also indirectly, since it doesn't have direct access to NavigatonService available to the View).

Another way to think about the ViewModel is like so: the ViewModel is the complete user-facing state of the system. In other words, this state and nothing else would be used by the View to show/present this state in some user-understandable way.

About Commands vs. Events:

Unfortunately, not everything in WPF is exposed as a Command. Buttons generate Commands, but not all controls do. Luckily, you can use Behaviors to translate Events to Commands and some frameworks provide the implementation. Here's an example of how MVVM Light does this. Blend also provides this functionality.

Also, why do you need to generate Commands in the code-behind? Frameworks like MVVMLight provide an implementation of a RelayCommand (or DelegateCommand) that removes the need to create different ICommand implementations. You can just as easily implement it yourself.

Community
  • 1
  • 1
New Dev
  • 48,427
  • 12
  • 87
  • 129