I'll be honest, there's a lot of MVVM frameworks out there, all promising to be the bees knees, light weight, etc. One of the common threads between all of them is the insistence on using their brand of dependency injection to do the job. There's good reasons to use dependency injection when you have a big enough project, and there's also a lot of good reasons not to use dependency injection for small utility projects.
MVVM In a Nutshell
Model-View-View Model isn't a new pattern, and there's a couple flavors out there. The basic pattern works like this:
- Model -- the representation of application data with bind-able properties.
- ViewModel -- a layer with a bind-able Model property that handles view specific logic
- View -- the user control or window that is shown to the user that binds directly to the ViewModel and Model.
DHaven.MicroMVVM
This was my attempt at making something that is as unopinionated as is reasonably possible. It supports both View First and Model First development, and it doesn't require you to use a dependency injection library if you don't want it. Of course there isn't anything to get in the way of you using your favorite one if you need it.
The Core micro-framework handles the common MVVM-isms pretty well. The core can also be used with Universal Apps, but I'm still working on the counterparts to that world. The basic model just needs to extend the ObservableObject class.
public class NameModel : ObservableObject
{
public string Name
{
get { return GetValue<string>(nameof(Name)); }
set { SetValue(nameof(Name), value); }
}
}
This is enough to implement the INotifyPropertyChanged semantics for any property. It won't send the notification if the value isn't actually different, as should be the case. Too many events can cause WPF to become unresponsive, so this helps with superfluous eventing.
You can make your Model read-only to ensure nothing gets changed by calling the protected method MakeReadOnly(). Any attempts to set a property after that will throw an ArgumentException. You also have an explicit protected method to RaisePropertyChanged() events yourself.
The base ViewModel<T> class just defines one property: Model. In order to create your own view model you simple extend that class:
public class NameViewModel : ViewModel<NameModel>
{
public NameViewModel(NameModel model = null)
: base(model)
: base(model)
{}
}
This is all standard stuff. The constructor provided allows you the flexibility to provide the model instance you want it to use, or to not have a model assigned initially. If you want the model to be created brand new when you create your view model that's easy too:
public class NameViewModel : ViewModel<NameModel>
{
public NameViewModel() : base(new NameModel())
{}
}
The last important piece is the command object. No MVVM framework is complete without some form of delegate based ICommand, and this one is no exception. You can either have parameterless actions or you can use the single object parameter. So let's give a demonstration:
public class NameViewModel : ViewModel<NameModel>
{
public NameViewModel(NameModel model = null) : base(model)
{
OkCommand = new RelayCommand(SaveChanges, CanSaveChanges);
}
public RelayCommand OkCommand { get; }
private bool CanSaveChanges()
{
return !string.IsNullOrEmpty(Model.Name);
}
private void SaveChanges()
{
// Call whatever is necessary to persist the changes.
// This is where you have the flexibility to use domain
// models, services, or just implement the logic here.
}
}
Of course, if you don't provide the Func<bool> parameter to enable or disable the button then it will always be enabled. Also, if one of the methods requires an object parameter, they both do.
More to come
So this introduction to the core micro-framework is getting long enough, I'll introduce the WPF side of the framework which has the remaining concepts that go beyond the basic MVVM core framework. You can see the interfaces and the models that go along with dialog boxes and window management in the core framework, but the implementation of that is going to be in the respective UI specific part of the framework. This is where the good stuff is going to come to play.
Comments
Post a Comment