Skip to main content

Release 1 of DHaven's MVVM micro-framework

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.
The two flavors are "View First" and "Model First".  View First MVVM has the view layer reference other view layers which load (or bind) their view model directly.  Model First MVVM has the view layer react to the view models and load the appropriate view at run time.

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)
    {}
}

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

Popular posts from this blog

Release 1 of D-haven.org's BibleUtilities

I'm one of a small team that is maintaining our church's web site.  The site has audio, transcripts, devotionals, etc. to help you with your Bible study.  As you can imagine, as time flies and different teams maintain the data, we had a big data problem (not "big data", just a large problem with data) on our hands. One of the things we needed to do was to scrape our transcripts to find all the scripture references in the text.  That's easier said than done since the rules for writing a Bible reference is a bit all over the place.  Add to that multiple ways to abbreviate the books of the Bible, and we've got a non-trivial problem. Bible Utilities The Bible parsing code lived as part of the church's source code until one day when a young Norwegian college student needed help with the same problem.  I helped him out initially with the source code, but since this is a common enough problem I made it an official Nuget package: DHaven.BibleUtilities .  Yo

Hello World!

It seems that in every tutorial, the first task is to print the words "Hello World!" in some fashion.  Every tutorial for every language, framework, etc. has the same task.  Why? Because it's the hook.  The thing that gets you invested.  You start thinking to yourself, "Look how easy that was!  I can do anything with this shiny new tool!"  This first post is no different.  It's testing the waters for my new blog. I've been a software engineer for more than a score (that's 20 years if you don't speak 19th century English) and I've seen fads come and go.  I've been in arguments about "The one true way" only to find that my understanding had been lacking.  I don't do that as much anymore, since I've broadened my horizons by learning new tools and ways of thinking about writing software.  What I've learned over the years is that Albert Einstein got it right when he said, "Everything should be made as simple as pos

The Impossible Deadline

If you've been in the game long enough, you get informed by upper management of a grand promise due in just a little over a month.  Something like rewriting an entire suite of applications in a new technology in 6 weeks.  That's what I'm facing at the moment.  The promise has been made, so after you pick your jaw up off the floor, what can you do? Do What You Can The number one thing that causes your gut to tie itself in knots is all the stuff you know you don't know.  The unknown things linger in your mind like a cancer undermining anything possible.  Norman Vincent Peale is credited with the quote "Shoot for the moon. Even if you miss, you'll land among the stars."  Aside from the bad astrophysics, that sentiment is what you need to start with.  Be aware of the deadline, but don't let it consume you.  It's too easy to spend a lot of energy fretting over it that is better spent on just getting stuff done. Get the Griping Out of the Way It&