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.
Related
I have developed my first WPF applicationa (tryingt) to use MVVM. I'm still learning and would appreciate the following questions answered:
Should I keep TestReportItem class in Repository class library or move it to it's own class library?
My ViewModel does not reference a Model. It refererences the class TestReportItem. I display the TestReportItem using XAML and a datatemplate to access a string field "Title". Is this acceptable/best practice?
TestReportItem
public class TestReportItem
{
public string Title { get; set; } = string.Empty;
public string SubTitle { get; set; } = string.Empty;
public bool HasTable { get; set; }
public string Reference { get; set; } = string.Empty;
public bool HasAdditionalInformation { get; set; }
}
TestReportItemRepository
public interface ITestReportItemRepository
{
List<TestReportItem> GetAllTestReportItems();
TestReportItem GetByName(string testName);
}
XMLTestReportItemRepository
public class XMLTestReportTestStandardRepository : ITestReportItemRepository
{
private string _filePath;
public string FilePath
{
get { return _filePath; }
set { _filePath = value; }
}
public XMLTestReportTestStandardRepository(string sourceFilePath)
{
FilePath = sourceFilePath;
}
public TestReportItem GetByName(string testName)
{ ... }
public List<TestReportItem> GetAllTestReportItems()
{ ... }
MVVM is a rule of thumb and not a dogma; meaning its really flexible. Originally MVVM was based off of the three tiered data organization system. View/Business layer/DB layer. And in a sense, it is just that.
Should I keep TestReportItem class in Repository class library or move it to it's own class library?
Whether your classes reside with the main project or in an external class library is up to the design. If the design calls for reuse between different projects, then yes extract it. Otherwise being external does not add any value except in separation of work.
Remember that an external library is in a sense a different namespace to structure your code.
My ViewModel does not reference a Model. It refererences the class TestReportItem.
As to TestReportItem it is a Model. Just because it has/may have methods and operations is moot. If one needs create partial class files where the model esque properties are contained in one partial and the operations et all are in another partial are fine and one achieves separation. But that is optional
datatemplate to access a string field "Title". Is this acceptable/best practice?
Does Title get derived or generated by its being in the class. If it does, then yes, if not, place Title on the main VM and extract/build it in the getter of Title.
I am trying to understand and implement different UI patterns in .NET to see the pros and cons and where they suite best.
I understand the main concept but I was creating an app and a question appeared.
Say we have a class Customer, which represents the core Information of a customer.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public string PhoneNumber { get; set; }
}
Now, if I create a WebView or WebForm to show all customers I can use this class to set as source f.e. to a DGV, being able to show all properties above.
But then I want to show for example a View/Form with the Revenue history of each customer.
So there is a class CustomerRevenue like
public class CustomerRevenue
{
public Revenue ActualYearExpectedRevenue { get; set; }
public IList<Revenue> RevenuePerYearList { get; set; }
public decimal ActualYearProjectedRevenue => CalculateYearProyection();
public decimal CalculateYearProyection(int year)
{
var daysInYear = DateTime.IsLeapYear(year) ? 365 : 366;
var actualYearRevenue = RevenuePerYearList.SingleOrDefault(x => x.Year == year);
var dayNumber = DateTime.Now.DayOfYear;
var projection = ((actualYearRevenue.Amount * daysInYear) / dayNumber);
return projection;
}
}
Here, to set RevenuePerYearList we need some time, since let's say we sell a lot and have a huge list of sells with huge lists of articles, so the calculation needs some time.
So now my question:
Should I then have "concrete" classes for each view/model with the data I want to show, i.e. here I would have apart of Customer class, say a CustomerRevenueModel
public class CustomerRevenueModel
{
private readonly CustomerRevenue _customerRevenue = new CustomerRevenue();
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
public CustomerRevenue CustomerRevenue
{
get { return _customerRevenue; }
}
}
}
which has (maybe) different properties, so I need to load this "heavy" properties when needed
or
should I stay with only one class (I mean, a customer always has a revenue) and leave the properties "empty"?
The first option makes me have a lot of classes, one for each view/form I want to show data for (maybe being able to reuse some models in various views/forms) but keeps all clean and in a valid state. And also each class can have it's own logic (domain logic - DDD)
The second option is less classes, less code, but some way I end having a huge (God) class, with all the properties a Customer has and all it's logic (methods). I load only the ones I need, but this appears really bad to me.
The third option is to have the big class with all properties and methods as my (domain)model, and create a "ViewModel" (which contains no methods, only props) each time I need to show sth. like above , using it as source for my GridView. This is the solution with more classes and code (big class + ViewModels + (maybe) DTOs), but also the more organized and SOLID design to my eyes... Here the use of a Mapper like AutoMapper would really help, mapping between objects
But this is the part I'm confused about...
Are these "ViewModels" a bad pattern using MVC or MVP?
Are this the same as the VM in MVVM? Which I Think not, since I've understood VM in MVVM like a "template", but what I talk about appears to me more like DAOs??
Or they don't have nothing to do, are just DAOs
I think I am a bit confused about all the different meanings of Model, ViewModel etc, in the different design patterns.
I am hardly trying to understand right MVC,MVP,MVVM and DDD and I think sometimes I am mixing terms...?
First, try to not "mix" things from different patterns, ViewModels are for MVVM, and you NEED ViewModels if you want to implement MVVM (ASP.Net MVC uses something called ViewModels, but it is not the same than the ViewModels in MVVM design pattern)
The ViewModel is like a model for the View. The ViewModel work is to "convert" the Model(s) to something the View can understand.
You can have one o more models (or none) and use it in the ViewModel, you have a ViewModel for each View.
In your example (a datagridview) you can have a model that will represent the data in a datagridview, a DTO if you want, and you can have a property in the ViewModel, a List and you will fill with data loaded from the database. In the View, you will bind that property (the list) to the dgv datasource.
Think that the ViewModel is something like the code behind of the view, but you are working with properties and commands that will be binded to controla in the view.
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.
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.
I am having a problem understanding how to propagate a property changed event in a Model class up through the ViewModel and into the view. I am trying to conform to the MVVM pattern so please keep that in mind.
I have a Model that I am trying to expose by the ViewModel. My Model class queries an Api call to get the server status and exposes that status in public properties. Ex:
public class ServerStatusRequest : ApiRequest
{
//Exposable properties by request
public ServerStatusHelperClass Status { get; set; }
Where ServerStatusHelperClass is just a wrapper for the combined results in the query:
public class ServerStatusHelperClass
{
public bool ServerStatus { get; set; }
public int OnlinePlayers { get; set; }
The cool thing about my ApiRequest base class is that it checks the cache time of a particular Api call and updates the Results by using a System.Timers.Timer. So, for example, the ServerStatus Api call is cached for 3 minutes on the Api, so every 3 minutes my ServerStatusApiRequest object will have fresh data for it. I expose a UpdatedResults event in all ApiRequest classes to notify when new data comes in.
Now I want my ViewModel to have an instance of ServerStatusApiRequest and bind to its ServerStatusHelperClass Status property and stay up to date with the changes every time the information is updated, but my view (for binding) can't know about my model, and thus, doesn't know about my UpdatedResults event in my ApiRequest class. How can I reflect that out to the View through my ViewModel? Am I doing something completely weird here?
Here is what I have that is semi-working but I feel is a very hacky solution:
In my ViewModel:
public const string EveServerStatusPropertyName = "EveServerStatus";
private ServerStatusRequest _eveServerStatus = new ServerStatusRequest();
public ServerStatusRequest EveServerStatus
{
get
{
return _eveServerStatus;
}
set
{
//if (_eveServerStatus == value)
//{
// return;
//}
//RaisePropertyChanging(EveServerStatusPropertyName);
_eveServerStatus = value;
RaisePropertyChanged(EveServerStatusPropertyName);
}
}
public void UpdateEveServerStatus(object sender, EventArgs e)
{
EveServerStatus = (ServerStatusRequest)sender;
}
And in the ViewModels constructor I subscribe to the Model's event:
EveServerStatus.UpdatedResults += new UpdatedResultsEventHandler(UpdateEveServerStatus);
As you can see, this seems extremely redundant. And I also ran into a problem where I had to comment out the check in the setter for EveServerStatus because at that point the _eveServerStatus was already updated to value just without it knowing and I wanted to fire the event anyway.
I fell like I'm missing a key concept here to link this all together much more easily.
Thanks for any input.
I have come across a much better way to implement the behavior I was looking for. Here is the code in my ViewModel:
private ServerStatusRequest _eveServerStatus = new ServerStatusRequest();
public ServerStatusRequest EveServerStatus
{
get
{
return _eveServerStatus;
}
}
No setter as my ViewModel nor my View should be changing this data. And Inside my ServerStatusRequest class I have a property exposing the ServerStatusHelperClass object as shown in the Question. I have changed the ServerStatusHelperClass and made it implement INotifyPropertyChanged as so:
public class ServerStatusHelperClass : ObservableObject
{
private bool _serverStatus;
public bool ServerStatus
{
get
{
return _serverStatus;
}
set
{
_serverStatus = value;
RaisePropertyChanged("ServerStatus");
}
}
...
ObservableObject is just a simple class that implements INotifyPropertyChanged for me from mvvmlight.
By doing this my View is automatically updated when my ApiRequest class modifies it's ServerStatusHelperClass object.
Input on this solution is welcome.