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.
Related
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 always wondered what the best practice is for separating code in a class based language. As an example, I made a project that handles api interaction with my web api. I want to know what the right option is to go with, or another suggestion.
Example 1
Project Files
Api.cs
DataTypes
Anime.cs
Episode.cs
Api.cs
public class Api
{
public static async Task<List<Anime>> GetAnimesByKeyword(string keyword)
{
// Execute api request to server
return result;
}
public static async Task<List<Episode>> GetEpisodesByAnime(Anime anime)
{
// Execute api request to server
return result;
}
}
DataTypes -> Anime.cs
public class Anime
{
public string Name { get; set; }
public string Summary { get; set; }
// Other properties
}
DataTypes -> Episode.cs
public class Episode
{
public string Name { get; set; }
public Date ReleaseDate { get; set; }
// Other properties
}
Or example 2
Project Files
Api.cs
DataTypes
Anime.cs
Episode.cs
Api.cs
public class Api
{
// Nothing for now
}
DataTypes -> Anime.cs
public class Anime
{
public static async Task<Anime> GetById(int id)
{
return result;
}
public string Name { get; set; }
public string Summary { get; set; }
// Other properties
}
DataTypes -> Episode.cs
public class Episode
{
public static async Task<List<Episode>> GetEpisodesByAnime(Anime anime)
{
return result;
}
public string Name { get; set; }
public Date ReleaseDate { get; set; }
// Other properties
}
What of these 2 is the preferred way of structuring the code, or is there a better way to do this. It might seem insignificant, but it does matter to me.
Thanks for helping me out!
In general, follow the Single Responsibility Principle. In practice this means you have simple objects that are data-only and more complex service classes that do work like loading from an external service or database.
Your second example mixes concerns AND it binds these two classes together tightly (Episode now depends on Anime). You can also see how it's hard to decide which class to put that loading method on: should it be anime.GetEpisodes() or Episode.GetEpisodesByAnime()? As the object graph gets more complex this escalates.
Later you may well want a different data transfer object for an entity. Having simple data-only objects makes it easy to add these and to use Automapper to convert.
But (on your first example) don't use static methods because that makes your service class harder to test. One service may depend on another (use dependency injection) and to test each in isolation you don't want to have static methods.
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 trying to separate/refactor code into folders and move all my 'Fill' properties into a logical place.
Is there a technical name for populating properties using a function
example:
public class AccountsView
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
This would be place in its own Class .. right now its within the above class
public static AccountsView FillCustomerView(Account data)
{
view.Email = data.Email;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
return view;
}
What would this 'FillCustomerView()' function be called?
The concept described here is called object mapping, and in this example it is implemented as a method on view model.
The drawback of this implementation is that it couples the view models to domain models, and this is usually frowned upon. To avoid this, mapper objects are typically used - they define projection from one model to another.
You could use some already existing implementation. Most popular seems to be Automapper, but there are others. E.g. the excellent ServiceStack framework also supports it.
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.