I'm wondering how to handle a ViewModel
in the traditional sense, which includes both properties and methods, and another "view model" which is simply just the properties -- perhaps the ViewModel would return a this view "entity", or something.
Let me explain:
Domain Model:
public class Workout
{
public int Id { get; set; }
public string Name { get; set; }
public string SomethingElse { get; set; }
public List<Exercise> Exercises { get; set; }
public DateTime CreatedDate { get; set; }
}
View Model:
public class WorkoutHistoryViewModel : IWorkoutHistoryViewModel
{
private IWorkoutRepository workoutRepository;
public WorkoutHistoryViewModel(IWorkoutRepository workoutRepository)
{
this.workoutRepository = workoutRepository;
}
// Here I'd like to return a slimmed down entity, not the full entity
public IEnumerable<WorkoutHistoryViewEntity> GetExistingWorkouts()
{
return this.workoutRepository.GetList(); // some mapping logic
}
}
And perhaps the desired "view entity" would just be:
public class WorkoutHistoryViewEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
I will also need to do something similar for, say, a WorkoutDetailsViewModel
, which will require a different set of properties for its "view model", like:
public class WorkoutDetailsViewEntity
{
public int Id { get; set; }
public string Name { get; set; }
public List<Exercise> Exercises { get; set; }
}
So, I guess the questions are:
- Am I doing MVVM all wrong? Should this ViewModel also have the desired properties on it? If so, then, when I do a
GetExistingWorkouts()
, am I really supposed to return aList<WorkoutHistoryViewModel>
? In that case, I'd have a bunch of objects, all with repositories and methods, when really I just want the data. - If I should create a third class, like the
WorkoutHistoryViewEntity
, what are these typically called (as ViewEntity doesn't really sound right).
2 Answers 2
You needn't worry about your ViewModels having more functionality than just providing data. That is, after all, their true function - to provide the data for display and any functionality required by the View. ViewModel's will normally contain properties, ICommands, at least one model and any references to services and repositories required to deal with modifications to the model.
In your case, your WorkoutHistoryViewModel
will provide an ObservableCollection<WorkoutViewModel>
, each of which has a Workout
object as it's model.
so to answer your 2 questions:
- You're doing MVVM just fine. Don't worry about it seeming a little verbose - there's reasons for the separation. And almost all viewmodels will have some references to services as well as data.
- Don't create a "ViewEntity". Just create a ViewModel.
-
Mark, the idea to use
WorkoutViewModel
sounds good, but I want it to be a totally stripped down version for thisHistory
view, but then I need to use a differentWorkoutViewModel
for, say, aWorkoutDetails
page, which will need many more properties than just the history list.Tom– Tom06/24/2015 14:16:58Commented Jun 24, 2015 at 14:16 -
Tom, you don't really need a striped down ViewModel, you need a stripped down view. I'd suggest using one fully specc'd out, all bangs and whistles WorkoutViewModel in both cases but Lazy<> load the advanced properties for when they're needed in the details page.Barracoder– Barracoder06/24/2015 14:22:51Commented Jun 24, 2015 at 14:22
-
Okay, I made this all work and it makes sense to me now. I was thinking each view could have it's own
POCO
to be mapped to, but that's overkill. Any view related to a workout exposes aWorkoutViewModel
in it's own specific ViewModelTom– Tom06/24/2015 18:42:36Commented Jun 24, 2015 at 18:42
Returning a List<WorkoutHistoryViewModel>
feels not as the way to go for me, even though it's done often. Your second option is better, and I think you got this quite right by intuition.
You are right though that WorkhoutHistoryViewEntity
is not an appropriate name. It could mean almost anything. It's hard to find a name for the Id and the name because the first one is technical and the second one isn't. I assume here that the Id is unique and the name isn't. In this case, is there probably a way to either return only a list of names or a list of Ids? This could solve your problem, because I wonder if there is a good reason to return both information together. If there is a good reason, telling us might make it more easy to find a good name. Else you can also go with WorkoutIdAndName
.
If both Id and name are unique, go with WorkoutReference
or WorkoutIdentifier
(and also use this class internal to store Id and an alias (here it would be the name)).