Property injection with Unity causing stack overflow - c#

I have been using Unity for quite a while but I have always used it with constructor injection. In an effort to reduce the number of classes I have to inject into my view models (as my commands rely on them) I thought I would try creating a concept that uses Property Injection and thus quash the requirement for the large constructor parameter lists. Here is the scenario...
I am creating a View Model that has Commands located on properties that use/update the hosing View Model in some way. I wish to pass the instance of the View Model into the constructors of the Commands located on the View Models properties. E.g.
public MainViewModel
{
public MainViewModel()
{
Customers = new ObservableCollection<CustomerViewModel>();
}
[Depedency("LoadCommand")]
public ICommand LoadCustomersCommand { get; set; }
public ObservableCollection<CustomerViewModel> Customers { get; private set; }
}
public LoadCustomersCommand : ICommand
{
public LoadCustomersCommand(MainViewModel mainViewModel)
{
//Store view model for later use
}
//... implementation
}
//Setup code in App.Xaml
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<ICommand, LoadCommand>("LoadCommand");
unityContainer.RegisterType<MainViewModel>(new ContainerControlledLifetimeManager());
When I resolve the MainViewModel class I get a StackOverflow exception (if Visual Studio comes back at all). Now I would expect Unity to create an instance of the MainViewModel first then as it is basically a singleton, then look at the instance of the View Model and create the Command passing in the newly created MainViewModel, but obviously I am wrong.
Any ideas?

This is Circular References error, and this as it said, this is developer's responsibility to avoid it. So MainViewModel references to LoadCustomersCommand wich is refferences to MainViewModel -> StackOverflow.
So the only you can do is
public class MainViewModel
{
public MainViewModel()
{
Customers = new ObservableCollection<CustomerViewModel>();
}
//no dependency.
public ICommand LoadCustomersCommand { get; set; }
public ObservableCollection<CustomerViewModel> Customers { get; private set; }
}
and to resolve you'll need to do the following
var mainModel = unityContainer.Resolve<MainViewModel>();
mainModel.LoadCustomersCommand = unityContainer.Resolve<ICommand>("LoadCommand");

Related

How to set a variable when a view is loaded using WPF MVVM app?

I have a UserControl view which require data to be pulled from the database to set the ObservableCollection in order to render a DataGrid.
I want to set the ObservableCollection when the UserControl is loaded not when the view model is constructed. Also, I prefer to asynchronously set the ObservableCollection so the UserContror opens immediacy then then the data-grid is set when the data becomes available.
In my view model I create a public method called SetVendors() which fetches the data from the database and sets ObservableCollection just before the view is notified. However, I am using the view class directly to set the SetVendors() method which sound like a bad practice for some reason to me.
Questions
Is it possible to set the data on view-load directly from the view-model? If so, how? Also, is it possible to set the data asynchronously so the view loads quick?
Here is my ViewModel code
public class VendorsListViewModel : ViewModel
{
protected IUnitOfWork UnitOfWork { get; set; }
public int CurrentPage { get; set; }
public int ModelsPerPage { get; set; }
public IPagedList PageMeta { get; set; }
private ObservableCollection<Vendor> _Vendors { get; set; }
public ObservableCollection<Vendor> Vendors
{
get
{
return _Vendors;
}
set
{
_Vendors = value;
NotifyPropertyChanged();
}
}
public VendorsListViewModel(IUnitOfWork unitOfWork)
: base()
{
UnitOfWork = unitOfWork;
CurrentPage = 1;
ModelsPerPage = 20;
}
public VendorsListViewModel()
: this(new UnitOfWork())
{
}
public void SetVendors()
{
var vendors = UnitOfWork.Vendors.Get(CurrentPage, ModelsPerPage);
Vendors = new ObservableCollection<Vendor>(vendors);
PageMeta = vendors.GetMetaData();
}
}
This is how currently set the data from the code behind the view which sound like a bad practice to me.
public partial class Index : UserControl
{
public Index()
{
InitializeComponent();
}
// This event is called from the view when the form is loaded using `Loaded="ViewLoaded"` XAML code
private void ViewLoaded(object sender, EventArgs e)
{
(DataContext as VendorsListViewModel).SetVendors();
}
}
Loading the data from the view´s code behind is indeed a bad practice as you are breaking the MVVM separation of concerns.
A better way to do that would be using a command, or, more precisely an event to command, check this article for a nice explanation.
To achieve this you can use the System.Windows.Interactivity library that comes with Blend for Visual Studio SDK for .NET, if you don't have it just run the Visual Studio installer and select it.
Then add a reference to the library by going to Add reference -> Assemblies -> Extensions.
Once you have this, things are simple really, you need to just:
First add the namespace to your View:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Then, bind the event to a command in your view model like this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Now in your ViewModel we have a little problem, we need to provide a command to be called when the event is triggered, a command is an implementation of the ICommand interface, all MVVM frameworks out there will provide you with ready to roll ICommand implementations so you can either use one of these frameworks or you can implement ICommand yourself if you just need it for this particular example, wait! you don't need to implement it, you can just get it from this question ,-)
For my example, however, I will use MVVM Light toolkit which I recommend you to use as it will relief you from most of the MVVM annoyances that you will need to deal with in any real-world application.
You can get MVVM Light from NuGet:
Install-Package MvvmLight -Version 5.4.1
So now you can use MvvmLight implementation of ICommand which is called RelayCommand, you would do so in your ViewModel as follows:
[...]
public ICommand LoadedCommand { get; private set; }
public VendorsListViewModel(IUnitOfWork unitOfWork) : base() {
UnitOfWork = unitOfWork;
CurrentPage = 1;
ModelsPerPage = 25;
LoadedCommand = new RelayCommand(this.Loaded);
}
private void Loaded()
{
SetVendors();
}
As per your second question: absolutely, you can load the data asynchronously if you want to. This is a whole different question though, take a look at this article for more info: https://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/

Two ViewModels are using one Model which holds data

I've searched for almost 3 hours and found alot about PRISM and VM data sharing, but I can't get my brain to understand it.
I have the two ViewModels MainViewModel and ListViewModel. The MainViewModel has a dockpanel where I want to have a common menu to add, remove items and close the application for example. There is also a usercontrol in the XAML which is showing the ListView. The ListView contains a few ObservableCollection<ProjectModel>.
From the MainVM I want to add more Projects - so to a collection. To access the ListModel, which contains the data, I pass it to the constructor of both ViewModels:
public MainModuleViewModel(ListModel listModel)
{
ListModel = listModel;
InitializeCommands();
}
public ListModuleViewModel(ListModel listModel)
{
ListModel = listModel;
InitializeCommands();
}
But it seems that during initializaiton to different objects of ListModel are created.
So my question is: What do I have to do, to work just on the one object of ListModel, which I'm passing to the constructors?
You have two options, as always:
register the ListModel as singleton (ContainerControlledLifetimeManager in Unity)
or register a service as singleton that gives the data to the view model
I'd go with the second one as it's far more flexible - you can use a different ListModel instance elsewhere with different content, you can make the service to give each view model its own instance (though with the same content) or you can make it give each view model the same instance and so on...
public interface IDatasource
{
ListModel Data { get; }
}
internal class StephensService : IDatasource
{
ListModel Data { get; } = new ListModel(); // or however you plan to procure the data
}
// ... bootstrapper / module initialization ...
Container.RegisterType<IDatasource, StephensService>( new ContainerControllerLifetimeManager() );
// ...
internal class ListModuleViewModel
{
public ListModuleViewModel( IDatasource datasource )
{
var heresMyData = datasource.Data;
}
}
Depending on your needs, the service can implement INotifyPropertyChanged or the ListModel can be an ObservableCollection...

Direct binding between UI and Model issue within MVVM application

I have a WPF application with MVVM.As I understood, the main goal of MVVM is to separate between logic layer and UI layer.
I have this Model class :
public class User
{
public string Login{get;set;}
public string Pwd{get;set;}
public List<User> GetUsers()
{
//
}
}
in my ViewModel, I instanciate a User object and an ObservableCollection of User
public class UserVM
{
public User _User{get;set;}
public ObservableCollection<User> liste{get; private set;}
public UserVM()
{
_User = new User("TODO","PWD2");
liste = new ObservableCollection(_User.GetUsers);
}
}
I feel that I bind directly a UI properties to a model object,So I need To know :
When I bind UI properties to the object _User properties, did I respect the MVVM architecture?
When I bind a listview datasource to liste, did I respect the MVVM architecture?
For the first question, if it is not suitable for MVVM, is it better to expose the model's properties instead of declaring the class?
For the second question, if it is not suitable for MVVM, How can I fix it ?
Thanks,
It looks like your User class has a tree-like structure in that it contains a List of User objects which themselves may contain a List of User objects...
The problem here is that your view model class contains User objects. Only the UserVM model would contain an ObservableCollection for example.
A simple fix would be: EDIT user.GetUsers() doesn't return a List<UserVM>
public class UserVM
{
public string Login { get; set; }
public string Pwd { get; set; }
public ObservableCollection<UserVM> Users { get; private set; }
public UserVM(User user)
{
Login = user.Login;
Pwd = user.Pwd;
Users = new ObservableCollection<UserViewModel>(
user.GetUsers().Select(subUser => new UserViewModel(subUser)));
}
}
You may also want to implement INotifyPropertyChanged so that the view gets notifications that the view model has changed.

Is it good Practice Call Business Logic from ViewModel

I am working on a large ASP.NET MVC Project(about 15 separate projects). We are using a Facade Design Pattern to call Business logic as well as other Projects.
Question: in MVC application is it a best practice to call a Facade from the ViewModel?
I am using single facade instances to call all the functions. I create a ViewModel for each Action and populate it with data from within the ViewModel. These results are making the ViewModel larger, but the Controller Action gets thinner because we are doing the work in the ViewModel now. In the ViewModel constructor I pass the facade instance and take what's needed from the business logic layer.
public class MyViewModel
{
private Facade _Facade;
public IEnumerable<SomeModel> Collection { get; set; }
public IEnumerable<SelectListItem> Years { get; set; }
public IEnumerable<SelectListItem> Quarters { get; set; }
public int SelectedYear { get; set; }
public int SelectedQuarter { get; set; }
public BottomUpForecastViewModel(EXFacade facade)
{
this._Facade = facade;
this.Years = GetFinancialYears();
this.Quarters = GetFinancialQuarters();
this.SelectedYear = DateTime.Now.Year;
this.SelectedQuarter = TimePeriods.GetQuarterNoForDate(DateTime.Now);
Collection = GetMonthlyCollection(SelectedYear, SelectedQuarter);// Take data from the _Facade(call facade)
}
}
public class MyController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult BottomUpForecast()
{
return View(new MyViewModel(facade));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult BottomUpForecast(MyViewModel model)
{
return View();
}
}
Is this good practice?
Do you have a suggestion for a better approach taking into consideration that we don't need to worry about Dependencies?
UPDATE : I found an interesting article about how to make controllers Lean "Put them on a diet": http://lostechies.com/jimmybogard/2013/12/19/put-your-controllers-on-a-diet-posts-and-commands/**
Your idea is correct. Perfectly acceptable to call business logic from View Model. I do it all the time.
Unfortunately, your current implementation is strongly coupled to concrete types. You could use a little abstract refactoring:
In stead, in your Business layer, create an Interface, IEXFacade to pass bind your object and pass to your ViewModel:
public interface IEXFacade
{
public IEnumerable<SomeModel> GetMonthlyCollection(int SelectedYear, int SelectedQuarter);
public IEnumerable<SelectListItem> GetFinancialYears();
public IEnumerable<SelectListItem> GetFinancialQuarters();
public int getSelectedYear();
public int getSelectedQuarter(DateTime dateTime);
}
and your EXFacade definition would look something like:
public class EXFacade : IEXFacade
{
private TimePeriods _timePeriods = new TimePeriods();
public int getSelectedYear()
{
return DateTime.Now.Year;
}
public int getSelectedQuarter (DateTime dateTime)
{
return _timePeriods.GetQuarterNoForDate(dateTime);
}
public IEnumerable<SomeModel> GetMonthlyCollection()
{
....
return MonthlyCollection;
}
public IEnumerable<SelectListItem> GetFinancialYears();
{
....
return MonthlyCollection;
}
public IEnumerable<SelectListItem> GetFinancialQuarters();
{
....
return MonthlyCollection;
}
}
Now your View Model would take IEXFacade and would be more tolerant of change
public class MyViewModel
{
MyViewModel(IEXFacade facade)
{
Years = facade.GetFinancialYears();
Quarters = facade.GetFinancialQuarters();
SelectedYear = facade.getSelectedYear();
SelectedQuarter = facade.getSelectedQuarter (DateTime.Now);
Collection = facade.GetMonthlyCollection(SelectedYear, SelectedQuarter);
}
//Keeping the Facade Object seems extraneous (unless I'm missing something)
//private Facade _Facade;
public IEnumerable<SomeModel> Collection { get; set; }
public IEnumerable<SelectListItem> Years { get; set; }
public IEnumerable<SelectListItem> Quarters { get; set; }
public int SelectedYear { get; set; }
public int SelectedQuarter { get; set; }
}
The goal is to de-couple dependence on your specific implementation of your EXFacade class by passing an interface. Now your EXFacade methods logic can change without breaking your view model. As long as the Interface (properties and signatures) remain the same.
Conclusion:
I'm not partial to calling logic directly from my ViewModel, as opposed to my Controller. But, it's often more convenient as it saves a step. Conversely, logic injected directly into your model is less obvious than if you consolidate it into your controllers. But the argument about "Fat Controllers" vs "Fat Models" is pretty even sided and I don't think either side is more correct.
What's more important is to understand that the Facade Pattern is meant to be an interface between your "Chatty" Logic Layer and your Presentation Layer. For the sake of Abstraction and de-coupling, the pattern calls for an Interface. As soon as you abstract your Facade with an Interface you can further de-couple by using an IOC container like NInject to Inject your Facade into your controllers or Models.
I strongly recommend using the Dependency Injection pattern in a large project like this.
You'll be breaking the MVC pattern if you put business logic in the ViewModel. It's controller's job to construct the view, not the view constructing itself by receiving depenencies.
The ViewModel should be ignorant of other layers(View and Controller), thereby promoting loosely coupled architecture.
If your ViewModel becomes too large, you can create helper methods or classes just for constructing the ViewModel.
public class MyController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult BottomUpForecast()
{
return View(this.GetMyViewModel());
}
private MyViewModel GetMyViewModel()
{
var viewModel = new MyViewModel()
{
Years = this.facade.GetFinancialYears();
Quarters = this.facade.GetFinancialQuarters();
SelectedYear = DateTime.Now.Year;
SelectedQuarter = this.facade.TimePeriods.GetQuarterNoForDate(DateTime.Now);
Collection = this.facade.GetMonthlyCollection(SelectedYear, SelectedQuarter);
}
return viewModel;
}
}
// Thin ViewModel
public class MyViewModel
{
public IEnumerable<SomeModel> Collection { get; set; }
public IEnumerable<SelectListItem> Years { get; set; }
public IEnumerable<SelectListItem> Quarters { get; set; }
public int SelectedYear { get; set; }
public int SelectedQuarter { get; set; }
}
Interesting discussion about this topic here: https://stackoverflow.com/a/1464030/1027250
The view model is a model for the view. It should contain data (model) and any logic required to move that data into and out of the view. It shouldn't know anything about any other layers. It shouldn't even depend on the controller, never mind anything below that. It's the job of the controller to populate that view model so the job of the controller to invoke the business logic.
Just to add to #Yorro post, MVVM actually uses this pattern where VM is responsible for all such activities. It will be preferred to use Controller for such actions in MVC.

MVP and rich user interface

I want to implement MVP pattern for my application.
MVP Passive View actually. So I came to a problem, it's easy one,
but can't decide which path should I take, so
I want to ask you guru's, how to properly work with MVP and display rich UI.
I mean, let's assume we need to display some data, and customer wants it to be TreeView.
There is requirement, that if user select different treenode, then the application updates itself with
new data or something like that.
At this point, i'm not sure how to implement View.
(All view logic goes to presenter)
I don't think that it is a good idea, to expose WinForms class
ISomeForm : IView {
//Presenter will take control of this TreeView.
TreeView Host {
get;
}
}
or exposing my data models
ISomeForm : IView {
//View knows how to display this data
List<MyDataNodes> Items {
get;
set;
}
}
or using other View interfaces.
ISomeForm : IView {
//Presenter knows what Views presenter should display.
List<IDataView> Items {
get;
set;
}
}
Any suggestions?
I would go with the View Interfaces.
In WPF MVVM, the more view separation I have, the easier it is to manage the UI/Logic interaction along the way.
I had to solve this problem using a MVC pattern. You could expose the TreeView as you suggested in your first example. Then the presenter could subscribe some events of the TreeView. But if you go this way your presenter will probably have to subscribe a lot of events of differents controls on your form. I have chosen to have a single event on the form that sends messages to the controller (in my case). The messages are represented as a class and can have any information you need. This is how my message looks:
public class MvcMessage
{
public object Source { get; private set; }
public MessageType MessageType { get; private set; }
public Type EntityType { get; private set; }
public IList InvolvedItems { get; set; }
public int NumAffected { get; set; }
public EventArgs SourceEventArgs { get; internal set; }
/// <summary>
/// Name of property who changed its value. Applies to models implementing INotifyPropertyChanged.
/// </summary>
public string PropertyName { get; set; }
public MvcMessage(object source, MessageType messageType, Type entityType)
{
this.Source = source;
this.MessageType = messageType;
this.EntityType = entityType;
}
public void Reroute(Type newEntityType)
{
MvcMessage reroutedMessage = (MvcMessage)MemberwiseClone();
reroutedMessage.EntityType = newEntityType;
Controller.NotifyAll(reroutedMessage);
}
}
... where MessageType is a enum containing a lot of common commands and requests.
My IView interface then defines the event like this:
public delegate void ViewEventHandler(MvcMessage message);
public interface IView : IViewPage, IWin32Window
{
event ViewEventHandler ViewEvent;
...
}
You should go more along the lines of the two latter examples; the view shouldn't expose WinForm-ish details to the presenter. See this answer for details on handling exactly your problem with TreeView updating - especially item 5.

Categories

Resources