When using the MVP pattern, I often come across methods and members which don't seem to fall nicely within the View or Presenter classes...My question is: What rules do you use to decide what functionality lies which classes? I am relatively new to MVP, so please humour me.
TIA.
I tend to favor the Passive View variant of MVP so this is a non issue for me. In passive view pattern the View pretty much delegates anything more complex than a simple assignment to the presenter.
You wind up with a pattern that looks like this:
public class MyView: IView
{
private MyPresenter Presenter;
private OnEvent()
{
Presenter.DoSomething();
}
public string MyProperty
{
get{ return UIControl.Property;}
set{ UIControl.Property = value}
}
}
public interface IView
{
public string MyProperty{ get; set;}
}
public class MyPresenter
{
private IView view;
public void DoSomething()
{
...
view.MyProperty = something;
}
}
The only trick part is if you have a datagrid on your form. These require a lot of work to fit into a Passive View pattern.
It boils down to how much manipulation of the UI is going on. If the method consist a lot of direct access to individual controls then likely it belongs on the presenter. Otherwise it belongs on the view. The goal is to reduce the interaction between the view and the present to the minimum needed to fulfill the design of the software.
For example
Presenter.SetListTitle MyList.Name
For I = View.MyListStart to View.MyListEnd
Presenter.AddListItem MyList(I)
Next I
Presenter.ShowListAddBUtton
Presenter.ShowListDelButton
Should be placed in the presenter as below
Public Sub UpdateWithList(MyList as AList, View as AView)
Me.SetListTitle MyList.Name
For I = View.MyListStart to View.MyListEnd
Me.AddListItem MyList(I)
Next I
Me.ShowListAddBUtton
Me.ShowListDelButton
End Sub
Later if you decided to change your UI all you have to worry about is implementing UpdateWithList not SetListTitle,AddListItem, etc, etc.
Related
In the project I'm working on, I've added a base ViewModel class which contains some functionality and dependencies common to all ViewModels. It provides validation, messaging, dispatching and navigation services through the following properties:
IValidateProperties Validator { get; }
IMessenger Messenger { get; }
IDispatcherHelper DispatcherHelper { get; }
INavigationService Navigation { get; }
I use an IoC container to wire my dependencies, however I have a few options for how to handle these dependencies which are common to all of my ViewModels:
Inject them in the constructor. If I did this, then it would require adding these four arguments to the constructor of every single ViewModel and pass them to the base constructor. That's a lot of extra noise added to my code base, which I'd really rather avoid. Also, if I were to add another dependency at some point, that would require changing the constructor of every single ViewModel.
Use property injection. This is the approach I'm working with now. Unfortunately, it means not being able to access these properties until after the ViewModel has been constructed, resulting in the following workarounds:
private IValidateProperties _validator;
public IValidateProperties Validator
{
get => _validator;
set
{
_validator = value;
_validator.ValidationTarget = this;
}
}
private IMessenger _messenger;
public IMessenger Messenger
{
get => _messenger;
set
{
_messenger = value;
MessengerAttached();
}
}
protected virtual void MessengerAttached() { }
Make the properties static and inject them on app startup. This is easy for Messenger, DispatcherHelper and Navigation because they are used as singletons anyway. For Validator, I would need to add a static ValidatorFactory, and instantiate the Validator in the constructor using the factory. This way seems to be the cleanest way to do things, but I have this voice in the back of my head telling me that using statics like this is a bad idea.
I feel like option 1 is out of the question because of the large amount of noisy boilerplate code it would result in being added to my ViewModels. I'm still unsure whether 2 or 3 is the best way to go though. Is there a good reason that using statics is a bad idea in this case, or am I fretting over nothing?
Some people argue that statics lead to untestable code, but in this case it would actually make things easier to test. If I were to go with option 3, I could add the following class for all of my view model tests to inherit:
public abstract class ViewModelTestBase
{
protected readonly IValidateProperties ValidatorMock;
protected readonly IMessenger MessengerMock;
protected readonly IDispatcherHelper DispatcherHelperMock;
protected readonly INavigationService NavigationMock;
protected ViewModelTestBase()
{
ValidatorMock = Substitute.For<IValidateProperties>();
ViewModelBase.Validator = ValidatorMock;
MessengerMock = Substitute.For<IMessenger>();
ViewModelBase.Messenger = MessengerMock;
DispatcherHelperMock = Substitute.For<IDispatcherHelper>();
ViewModelBase.DispatcherHelper = DispatcherHelperMock;
NavigationMock = Substitute.For<INavigationService>();
ViewModelBase.Navigation = NavigationMock;
}
}
So, what concrete reasons are there for not going with approach #3? And if statics really are such a bad idea in this case, what concrete reasons are there for not going with approach #2 instead?
I'm writing a WPF application using MVVM. My ViewModels are quite large and have a lot of logic associated with them (filtering, searching, writing to the database, etc), so I've decided to try to separate out the logic of the ViewModels to a "Presenter" class like is used in MVP.
So, my basic setup is this:
public class FooViewModel : ViewModelBase, IFooViewModel
{
private IFooPresenter presenter;
private ObservableCollection<FooModel> fooCollection;
public FooViewModel()
{
presenter = FooPresenter(this);
}
public ObservableCollection<FooModel> FooCollection
{
get { return fooCollection; }
set
{
fooCollection = value;
OnPropertyChanged("FooCollection");
}
}
public void FooCommandMethod(object obj)
{
presenter.DoStuff();
}
}
public class FooPresenter : IFooPresenter
{
private IFooViewModel viewModel;
public FooPresenter(IFooViewModel viewModel)
{
this.viewModel = viewModel;
}
public void DoStuff()
{
viewModel.FooCollection.Add(new FooModel());
//etc etc, make whatever ViewModel updates are needed
}
}
I feel like it is bad practice to have this circular dependency (View Model depends on Presenter and Presenter depends on View Model). These classes could be combined into one large ViewModel class, but I do like how clean this approach keeps my View Models, all that they do is hold commands that call presenter functions and hold the Model/collections of the Model. I also dislike the dependency of the ViewModel on the concrete implementation of the Presenter. One approach I have toyed with is using a Service Locator type class, so it would look like this:
public FooViewModel()
{
presenter = PresenterLocator.GetPresenter<IFooPresenter>(this);
}
What I would prefer, though, is to use Constructor Dependency Injection to inject the controller when I create the ViewModel. The problem with this is that this creates a circular dependency in the constructors of the ViewModels and Presenters, which causes my application to crash when I attempt to achieve this using Unity. It ends up looking like this:
public FooViewModel(IFooPresenter presenter)
{
this.presenter = presenterl
}
And
public FooPresenter(IFooViewModel viewModel(
{
this.viewModel = viewModel;
}
So, my concern is that my design approach is inherently flawed due to this. Nevertheless, I really like how clean it keeps my ViewModels and separates them from Business Logic. Is there a better way I could be designing this? Is there any way I can use DI to achieve this? Or by doing that am I essentially trying to force a DI container to act as a Service Locator?
First of all, I would not call this a "presenter". This introduces an unwanted confusion, in fact your presenter doesn't present anything, it is just an extracted bit of code from a large view model. Have you considered calling it just "a service"? A SearchService for example?
Another question is: does such service always depend on a view model? Or rather, could it depend on lower layers (unit of works/repos for example) or other services? Note that because your service depends on a view model and you pass a view model directly there, you loose a control of what happens to the view model inside a service. Your DoStuff method is a perfect example, it does something to a view model, alters its state. Instead, you could have
public class FooViewModel : ViewModelBase, IFooViewModel
{
private IFooService service;
private ObservableCollection<FooModel> fooCollection;
public FooViewModel()
{
service = FooService(this);
}
public void FooCommandMethod(object obj)
{
// the responsibility on consuming service outcome is still here!
this.FooCollection.Add( service.CreateNewModel() );
}
}
public class FooService : IFooService
{
// constructor parameter not needed now
public FooService()
{
this.viewModel = viewModel;
}
public FooModel CreateModel()
{
return ...;
}
}
If you still insist however on having a circular dependency, make it so that one of the two has a parameterless constructor and a property injector:
public class FooViewModel : IFooViewModel
{
private IFooService _service;
public FooViewModel( IFooService service )
{
this._service = service;
this._service.Model = this;
}
}
public class FooService : IFooService
{
public IFooViewModel Model { get; set; }
}
This way Unity asked for a IFooViewModel will resolve a parameterless IFooService and then execute the constructor that sets the cycle for both parties.
After a major edit to this quesiton, I'm hoping it's now clear.
I'm very lost with binding in WPF when 1 change should affect multiple properties.
I regularly use VVM to bind my ViewModel to my View and I would say I'm OK with it.
I am trying to implement a state controller. This means that, what ever settings I made in part of my UI, the reflection is through out.
For example in my part of my UI, I can toggle a feature on or off, such as "show images"
When I make this change, I'd like everything in my application to be notified and act accordingly.
So, my StateController class will have a property
public bool ShowImages
And in my View, I'd likely have something like
<image Visible ="{Binding ShowImages", Converter={StaticConverter ConvertMe}}" />
The problem I have is how I go about making the StateController alert all of my ViewModels of this.
Currently, in each ViewModel I'm assuming I'd have to have the same property repeated
public bool ShowImages
EG
public class StateController : BaseViewModel
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
So, my question is, if I updated ViewModelB.ShowImages, how would I first inform the StateController which in turn updates all ViewModels.
Is this something the INotifyPropertyChanged can do automatically for me since they all share the same propertyName, or do I have to implement the logic manually, eg
public static class StateController
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelA : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
I hate the idea of the above implementation but it does show what I'm trying to achieve. I just hope there is a better way!
The PropertyChange notification is only raised for that one object model.
So raising a change notification of the "Name" property of ClassA will only update the UI in cases where it's bound to that specific ClassA.Name. It won't trigger a change notification for any ClassB.Name, or other instances of ClassA.Name.
I would suggest using a Singleton here for your StateModel, and having your other models subscribe to the StateModel.PropertyChanged event to know if it should update, like this answer.
public ViewModelA
{
public ViewModelA()
{
StateController.Instance.PropertyChanged += StateController_PropertyChanged;
}
void StateController_PropertyChanged(object sender, NotifyPropertyChangedEventArgs e)
{
// if singleton's ShowImages property changed, raise change
// notification for this class's ShowImages property too
if (e.PropertyName == "ShowImages")
OnPropertyChanged("ShowImages");
}
public bool ShowImages
{
get { return StateController.Instance.ShowImages; }
set { StateController.Instance.ShowImages = value; }
}
}
If I understood you correctly, you are looking for a mechanism that allows your different ViewModels to communicate between each other.
One possible way would be to implement the Observer Pattern (a code example can be found here: "Observer pattern with C# 4"). In this way your ViewModel subscribe each other to receive change notifications from a "publisher", i.e. the ViewModel that had its value changed. You have a good control over who receives which notification from which publisher. The downside of this approach is a tight coupling between your models.
My approach would be this:
Use a message dispatcher. Your ViewModels can subscribe to a certain type of message, e.g. ShowImagesChanged. If any of your ViewModels changed the ShowImages property, that ViewModel calls the dispatcher to send out such a ShowImagesChanged message with your current values.
This way you can keep you ViewModels decoupled from each other. Still, although the ViewModels do not know each other this gives a way to exchange data between them.
Personally, I have used the Caliburn Micro MVVM framework several times for this, but there should be enough other MVVM frameworks that provide the same functionality to fit your taste.
The Calibiurn Micro documentation and how easily the dispatcher can be used is here: Event Aggregator
To avoid code repetition you can create a class derived from BaseViewModel that implements your property and have ViewModelA, ViewModelB extend it. However, this does not solve the problem of keeping each instance updated.
In order to do so, you may:
Use a static class (your current solution) or a Singleton as suggested in one of the comments. This is simple but has potential problems such as race conditions and coupling.
Have your ShowImages binding property repeated in each ViewModel and update it by subscribing to a ShowImagesChanged event. This could be published through a Command executed from the UI. I'd say this is the WPF approach and has the benefit of decoupling the ShowImages state management from its consumption.
Assign the ShowImagesupdate responsibility to a single ViewModel and subscribe to the its PropertyChanged in the other ViewModels so that they update accordingly. Better than the first option, but still huge coupling.
Why repeat properties at all? Just bind to StateController itself.
Say we have singleton StateController:
public class StateController : INotifyPropertyChanged
{
private static StateController instance;
public static StateController Instance {
get { return instance ?? (instance = new StateController()); }
}
//here`s our flag
private bool isSomething;
public bool IsSomething
{
get { return isSomething; }
set
{
isSomething = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsSomething"));
}
}
private StateController(){}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
Then in base VM class just make a reference to this controller:
public StateController Controller { get { return StateController.Instance; } }
And where needed bind like this:
<CheckBox IsChecked="{Binding Controller.IsSomething}">
Test
</CheckBox>
This way every binding will work with one property and react to one property. If you need some custom code to work you can subscribe to PropertyChanged of StateController where needed and take action.
So..I intend to use a Model View Presenter(the "passive" mode, in which the UI is pretty dumb and sends all the events to the Presenter, and the Presenter takes care of dealing with the Model) to glue my domain's business logic and the UI.
My question is how should my Presenter look like. Is this what I want?
public class TicTacToeGamePresenter
{
private readonly ITicTacToeView view;
private readonly PlayerController model;
public TicTacToeGamePresenter(ITicTacToeView view) {
this.view = view;
}
...
}
Should I by constructor injection pass the instance of the intended ITicTacToeView? This would allow me to use this TicTacToeGamePresenter class with Forms, WPF, WebForms, etc. I would only have to make sure my View implements the ITicTacToeView interface.
Or should I just instantiate the kind of concrete classes I intend to use directly and just have a parameterless constructor? This seems kinda pointless, but I had to ask :( .
I currently have the ITicTacToeView interface defined as:
public interface ITicTacToePassiveView
{
event EventHandler<EventArgs<Point>> ButtonClicked;
void PlayerOPlayed(Point location);
void PlayerXPlayed(Point location);
void EnableStartButton();
void DisableStartButton();
}
One more thing. When coding the constructor of TicTacToeGamePresenter I ended up with this:
public TicTacToeGamePresenter(ITicTacToePassiveView view)
{
this.view = view;
IGameLogicAnaliser gameLogicAnaliser = new GameLogicAnaliser();
IPlayer playerO = new Player(gameLogicAnaliser);
IPlayer playerX = new Player(gameLogicAnaliser);
Game game = new Game(playerO, playerX);
this.playerOModel = new PlayerController(playerO, game);
this.playerXModel = new PlayerController(playerX, game);
}
Now, after looking to the code I reckon that maybe it'd be better to have this' class dependencies be made more explicit by giving the "class above" the responsability of class instantiation:
public TicTacToeGamePresenter(ITicTacToePassiveView view, IPlayer playerO, IPlayer playerX, Game game, PlayerController playerOModel, PlayerController playerXModel)
{
this.view = view;
this.playerO = playerO;
this.playerX = playerX;
this.game = game;
this.playerOModel = playerOModel;
this.playerXModel = playerXModel;
}
Which one would be better?
Thanks
I would go with your first option : using the constructor to inject the view into the presenter as it will allow you to support different types of UI provided they all implement the interface.
Also, from a unit testing perspective, your life will be much simpler as any mock class implementing that interface can be used for your testing
EDIT: Added code sample from how WCSF does it
WCSF uses dependency injection and every view has a property for the presenter that is injected into the view. This works just as well and there is no need for the constructor approach but this will need a public View property exposed.
[CreateNew]
public DefaultViewPresenter Presenter
{
set
{
this._presenter = value;
this._presenter.View = this;
}
}
I don't think you have much choice BUT to use constructor (or parameter) injection.
At runtime, your view will already be instantiated when its presenter first instantiates; if you create the view in the presenter, then you'll be working with a separate instance of your view, and none of the events you'll expect will be handled.
If you're using an IoC container to create your presenter, I'd favor the second approach to your constructor. If you're not, then you're asking your view to instantiate IPlayers, PlayerControllers and Games on behalf of the presenter, and it probably shouldn't know how to do that. Take a look here for some discussion on why you'd want to use an IoC container.
I have been reading a lot on MVC/MVP patterns.... I have a simple question....If you have a view with loads of controls....say 10 texboxes and 10 checkboxes....etc etc... Am I expected to specify the properties and events each one of them in my IView interface?....
Definitely not that way.
Your IView Interface will define set of contracts/ methods (it includes properties) that can be accessed by your business layer.
It is totally wrong to exposed your control in interface like this:
public interface IView
{
TextBox UserNameTextBox{get;set;}
}
You should not have interfaces defined in this way. This is really a bad programming.
You should rather expose some contracts that your UI layer will implement.
E.g.
public interface IView
{
public void SetUserName(string Text);
}
You can implement this interface on winform as well as webform.
Similarly, you are also not supposed to expose knowlede of UI in interface(Contract).
Lets assume a scenario where you have to display information of Employee object on UI.
You should pass Employee object to UI through this interface and UI will take care of way of representing this Employee object.
Your BL should never bother about n number of TextBoxes and checkboxes.
public class Employee
{
//first name
//last name
//is manager
//is teamleader
//address
}
public interface IEmployeeView
{
void SetEmployee(Employee employee);
}
public partial class EmployeeForm:WinForm,IEmployeeView
{
public void SetEmployee(Employee employee)
{
ENameTextBox.Text = employee.FirstName+" "+employee.LastName;
}
}