prism vs mvvm light for wpf
Asked Answered
P

3

33

We are starting a WPF with MVVM project and have to decide on PRISM or MVVM Light (I am new to both these frameworks). I have read through a few posts but still have a few questions. Can someone please throw some light on the following aspects w.r.t. both the frameworks?:

  1. Performance: Will either one framework perform better than the other for any reason?

  2. Communication within the app (viewmodel to viewmodel or between modules etc): I have read that MVVM Light has Messenging Service which appears to be fairly easy as well. But PRISM does not appear to have any equivalent. Is that true? How would PRISM handle interactions?

  3. Unit Testing: Have read that PRISM supports Unit Testing better. Can we still write NUNIT or VSTS tests in MVVM Light also?

Patrolman answered 10/12, 2013 at 5:58 Comment(3)
To answer your 2): Prism has an EventAggregator that does what you describe that MVVM does.Evvoia
In addition to emedbo's comment, you can find more related information for Prism communication in the Prism Guide chapter of Loosely Coupled Communication at MSDN.Nikolai
One of the best features of PRISM is Regions. It has EventAggregator for ViewModel to ViewModel comms. You could use Blend Behaviors (System.Windows.Interactivity, Microsoft.Expression.Interactions) for Interactions. Unit Testing depends on how well you write ViewModel unit test friendly rather than on the MVVM framework you use. So, If you do want Region support in your app then go with PRISM otherwise MVVM-Light. I do not know if there is a way to achieve Regions with MVVM-Light as well.Spill
G
22
  1. I just moved a project from Prism to MvvmLight and it seems to work faster (very subjective).

  2. Both Prism and MvvmLight have Mediator realisation (IEventAggregator in Prism, IMessenger in MvvmLight). But IMessenger has more abilities (for instance, sending messages with tokens) compared to IEventAggregator and is much more convenient to use (see next item).

    MvvmLight also has a more powerful ViewModelBase class.

  3. Applications that use MvvmLight are much easier to test than those that use Prism. For instance, IMessenger is easier to mock than IEventAggregator.

PrismViewModel.cs

using System;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;

// An ugly empty event class
public class StringEvent : CompositePresentationEvent<string> { }

public sealed class PrismViewModel : NotificationObject
{
    private readonly IEventAggregator _eventAggregator;

    private string _name;

    public PrismViewModel(IEventAggregator eventAggregator)
    {
        if (eventAggregator == null)
            throw new ArgumentNullException("eventAggregator");

        _eventAggregator = eventAggregator;
        _eventAggregator.GetEvent<StringEvent>().Subscribe(s => Name = s);
    }

    public string Name
    {
        get { return _name; }
        set
        {
            // boiler-plate code
            if (value == _name) 
                return;
            _name = value;
            RaisePropertyChanged(() => Name);
        }
    }

    public void SendMessage(string message)
    {
        _eventAggregator.GetEvent<StringEvent>().Publish(message);
    }
}

PrismViewModelTestCase.cs

using System;
using FluentAssertions;
using Microsoft.Practices.Prism.Events;
using NSubstitute;
using NUnit.Framework;

public class PrismViewModelTestCase
{
    private static PrismViewModel CreateViewModel(IEventAggregator eventAggregator = null)
    {
        // You can't return Substitute.For<IEventAggregator>()
        // because it returns null when PrismViewModel's constructor
        // invokes GetEvent<StringEvent>() method which leads to NullReferenceException
        return new PrismViewModel(eventAggregator ?? CreateEventAggregatorStub());
    }

    private static IEventAggregator CreateEventAggregatorStub()
    {
        var eventAggregatorStub = Substitute.For<IEventAggregator>();
        eventAggregatorStub.GetEvent<StringEvent>().Returns(Substitute.For<StringEvent>());
        return eventAggregatorStub;
    }

    [Test]
    public void Constructor_WithNonNullEventAggregator_ExpectedSubscribesToStringEvent()
    {
        // Arrange
        var stringEventMock = Substitute.For<StringEvent>();

        var eventAggregatorStub = Substitute.For<IEventAggregator>();
        eventAggregatorStub.GetEvent<StringEvent>().Returns(stringEventMock);

        // Act
        CreateViewModel(eventAggregatorStub);

        // Assert
        // With constrained isolation framework you can only mock virtual members
        // CompositePresentationEvent<TPayload> has only one virtual Subscribe overload with four parameters
        stringEventMock.Received()
                       .Subscribe(Arg.Any<Action<string>>(), Arg.Any<ThreadOption>(), Arg.Any<bool>(),
                                  Arg.Any<Predicate<string>>());
    }

    [Test]
    public void Name_ExpectedRaisesPropertyChanged()
    {
        var sut = CreateViewModel();
        sut.MonitorEvents();

        sut.Name = "any-value";

        sut.ShouldRaisePropertyChangeFor(vm => vm.Name);
    }

    [Test]
    public void SendMessage_ExpectedPublishesStringEventThroughEventAggregator()
    {
        // Arrange
        var stringEventMock = Substitute.For<StringEvent>();

        var eventAggregatorStub = Substitute.For<IEventAggregator>();
        eventAggregatorStub.GetEvent<StringEvent>().Returns(stringEventMock);

        var sut = CreateViewModel(eventAggregatorStub);
        const string expectedPayload = "any-string-payload";

        // Act
        sut.SendMessage(expectedPayload);

        // Assert
        stringEventMock.Received().Publish(expectedPayload);
    }
}

MvvmLightViewModel.cs

using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;

public sealed class MvvmLightViewModel : ViewModelBase
{
    private string _name;

    public MvvmLightViewModel(IMessenger messenger)
    {
        if (messenger == null)
            throw new ArgumentNullException("messenger");

        // ViewModelBase already have field for IMessenger
        MessengerInstance = messenger; 
        MessengerInstance.Register<string>(this, s => Name = s);
    }

    public string Name
    {
        get { return _name; }
        set { Set(() => Name, ref _name, value); // Chic!  }
    }

    public void SendMessage(string message)
    {
        MessengerInstance.Send(message);
    }
}

MvvmLightViewModelTestCase.cs

using System;
using FluentAssertions;
using GalaSoft.MvvmLight.Messaging;
using NSubstitute;
using NUnit.Framework;

public class MvvmLightViewModelTestCase
{
    private static MvvmLightViewModel CreateViewModel(IMessenger messenger = null)
    {
        return new MvvmLightViewModel(messenger ?? Substitute.For<IMessenger>());
    }

    [Test]
    public void Constructor_WithNonNullMessenger_ExpectedRegistersToStringMessage()
    {
        var messengerStub = Substitute.For<IMessenger>();

        var sut = CreateViewModel(messengerStub);

        messengerStub.Received().Register(sut, Arg.Any<Action<string>>());
    }

    [Test]
    public void Name_ExpectedRaisesPropertyChanged()
    {
        var sut = CreateViewModel();
        sut.MonitorEvents();

        sut.Name = "any-value";

        sut.ShouldRaisePropertyChangeFor(vm => vm.Name);
    }

    [Test]
    public void SendMessage_ExpectedSendsStringMessageThroughMessenger()
    {
        var messengerMock = Substitute.For<IMessenger>();
        var sut = CreateViewModel(messengerMock);
        const string expectedMessage = "message";

        sut.SendMessage(expectedMessage);

        messengerMock.Received().Send(expectedMessage);
    }
}

Disadvantages of Prism:

I think that any new project should be based on modern solutions and approaches. IMHO, any modern MVVM-framework (like Catel, Caliburn.Micro, MvvmLight, ReactiveUI) is much better than Prism.

Gluconeogenesis answered 13/12, 2013 at 16:18 Comment(3)
It's just plain wrong that prism is no longer developed.Matherne
Yeah, now it's wrong (new version of Prism released not so long ago). When I answered this question the future of Prism was pretty hazy. But IEventAggregator still lacks of testability (my answer still relevant).Gluconeogenesis
Please note that Prism has the BindableBase VM base class that provides a SetProperty() method to handle the RaisePropertyChanged() boilerplate, i.e.: the setter for Name would be: set { SetProperty(ref _name, value); }. Which then makes it almost identical to the MVVM Light VMPolaroid
G
9

You cannot fully compare Prism and MvvmLight.

Prism is more about application architecture even though Prism has been known as MVVM framework. Actually until Prism 5 it had nothing to do with MVVM and It didn't have BaseViewModel class in Prism 4.1 and in prior.

Prism is not a MVVM framework it is application framework it sits higher than that. Prism 5 introduced some support for MVVM and Prism 6 took it futher.

MVVM is just another aspect of problems that prism provides guidance to solve.

It is like comparing Angular vs. Knockout. AngularJS manages the whole application and defines guidelines on how the application code should be structured, whereas with KnockoutJS the application structure is entirely up to you. It is a similar case between Prism and MvvmLight.

Prism provides an implementation of a collection of design patterns that are helpful in writing well structured and maintainable XAML applications, including MVVM, dependency injection, commanding, event aggregation, and more. Prism's core functionality is a shared code base in a Portable Class Library targeting these platforms; WPF, Windows 10 UWP, and Xamarin Forms.

I would recommend to use Prism if you are developing an enterprise level application using wpf.

Please watch this Webinar about MVVM Made Simple with Prism. The presenter is Brian Lagunas: https://www.youtube.com/watch?v=ZfBy2nfykqY

Grenadier answered 11/12, 2016 at 2:45 Comment(0)
G
5

I don't believe MS has ever promoted PRISM as a "framework" in the same sense that MVVM Light, Caliburn, etc. are "advertised." My understanding is the PRISM was always presented to the "world" as a "practice." Which, I believe, simply means a organized way of building applications. It becomes a bit confusing because of all the code that is supplied with PRISM and one can consider it a "framework" that can be used to build applications. And, it's true, you can use the code that is supplied with PRISM to build applications of your own. But, PRISM, in my mind is much more complicated than the "frameworks" that are available for MVVM and there is a steep learning curve as well as the possibility of "overkill" and making your application more complex than is necessary. If you have the time to learn the latest "framework" or "practice" at the time you are building your application, that's GREAT! My experience has been that I don't have the luxury of factoring in learning some new "practice" or the latest "framework" but have to get the job done. In an ideal world, one would like to be able to use the latest and greatest "framework" or employ the latest "practices" but sometimes you just have to stick with what you already know and get it done.

Gracegraceful answered 21/7, 2014 at 22:7 Comment(3)
Hi and welcome to stack overflow. I'm not sure this "answers" the "question" here (also... a bit overmuch use of "scare quotes" makes this harder to "read" ;) ). The Original Poster asked three pretty specific questions, which aren't addressed in your response. Perhaps you could address those too? Otherwise I'd be classing what you wrote above more as commentary than an answer... and that means it more rightly goes in the comment section (just below the original question). Now - you don't yet have enough rep to comment... but if an answer is just a comment, it's swiftly deleted by reviewers.Dudleyduds
@TarynEast hasn't been deleted yet tho =)Xenophanes
Would you like me to? I can. ;) Note: you now have enough rep to move it into the comments section...Dudleyduds

© 2022 - 2024 — McMap. All rights reserved.