MVVM Calculated Fields in Model or ViewModel? - c#

I am trying to determine the correct pattern for handling Calculated fields or methods in MVVM. I have a number of calculated fields that will be required for both the presentation layer and some back end processing. Let say it is "CalculateTotal" which is based on summing a number of different values from the Data object and its sub objects.
I would like this calculation in one location. The first thought is that it belongs in the model (i.e., not the viewModel) since the model object will be passed to other back end processing systems. What is then the best way to make this available to the ViewModel?
Option 1, is that I statically load the viewModel when I create it based off the Model (e.g., vwModel.Total = model.CalculateTotal())
This suffers if I am needing to update the ViewModel dynamcally, for example I modify the underlying data and try to get the new total.
Option 2: More service oriented and each calculation calls a service to return the values. The issue I see with this is more performance based. Once I load my object once, I have all the data needed to perform the calculation. It seems each call would require the data object to be reloaded
Option 3: Have the ViewModel contain the data model and create methods to call the data model methods
Thoughts? Suggestions?

I would do all calculations in the model. The view model should subscribe to events (e.g. via INotifyPropertyChanged) on the model, so when the back-end values change, the view model will be notified.
The view model can, of course, interrogate the model for calculations and doesn't have to get all information through events. The above is only for when the data changes come directly from the model or the underlying data layer.

I would go with something like option 2. Moving the calculation logic out of the model and view model will simplify things and make that logic more reusable by other classes. From your question it seems like you already have an idea of how to implement that. Keeping the model "dumb" and having services/utility/helper classes that know how to process the model will help you in the long run if the model is being passed around a lot. Just something to think about but keeping the responsibility of a class very limited makes for easier code maintenance down the road. You might end up with more classes but I personally find it easier to focus and work on two or three small classes than one very large class. I don't know what type of application you have or how heavy the calculations are but unless you are having measurable performance issues I wouldn't worry about trying to pre-optimize things.

I would like this calculation in one location.
If there is a dedicated Service Layer, then almost all calculations should be done in Service Layer.
Option 1
Instead of using CalculateTotal method on Model, it's better make a read only property Total and calculate it in a service layer method every time Model is requested. This is the easiest and the best option to use if there are no performance issues, since it drastically simplifies ViewModel.
Option 2
Calling a dedicated CalculateTotal service method from ViewModel is the only option available if calculation process is resource intensive and calculated total is not used every time Model is requested.

Related

How to update WPF UI as database changes

I am writing an application in C#/WPF/Entity Framework DB first that communicates with a proprietary piece of industrial hardware that measures values like flow and temperature from a coolant line. Those values frequently are updated in my SQL Server database with a thread that runs in the background, and then are displayed in my UI.
My concern currently is with how I update my UI to reflect those changes. Here's an example of how I update a datagrid:
I set my datacontext to my viewmodel, and instantiate a thread that runs every second:
_DataContext = new ViewModels.SummaryTable_ViewModel();
this.DataContext = _DataContext;
UIUpdateThread = new Thread(UIUpdaterThread);
UIUpdateThread.IsBackground = true;
UIUpdateThread.Start();
The model my grid is based on is an IList<> that looks like this:
private IList<channel> _channel;
public IList<channel> Channels
{
get
{
return _channel;
}
set
{
_channel = value;
//NotifyPropertyChanged();
OnPropertyChanged("Channels");
}
}
Then every second my UIUpdateThread calls my FillChannels() method which is as follows, then the grid updates based on the propertychanged notification:
using (var DTE = new myEntities())
{
if (DTE.channels.Any())
{
var q = (from a in DTE.channels
where a.setup.CurrentSetup == true
orderby a.ChannelNumber
select a).ToList();
this.Channels = q;
}
}
So my question is this: is there a better, more elegant way to do this? This feels "wrong" for lack of a better term. And it has bad side effects, like resetting the user-set sort on my datagrid every time the thread runs. Also I think it breaks the MVVM pattern, though I'm not certain.
For example I'm thinking what if the thread that talks to my hardware updates a shared Channel object every time it polls the hardware for data, and I just bind my UIs to it, that way I wouldn't have to run this thread (or the other threads on my other UIs that do the same thing), just update based on PropertyChanged notifications. Or is there some other method I'm unaware of completely? When searching for an answer I saw mentions of the unit of work pattern, with which I'm unfamiliar, is that a relevant concept here?
As you can see, I'm not too sure where to go from here, and could really use some help. Sorry for the wall of text, I just wanted to be as thorough as possible. Any assistance would be greatly appreciated. Thanks.
I think your model should be the one that's notifying your view model when there is new data. You should put whatever mechanism that accomplishes this (like the timer I assume you're using) into the model.
Basically, your model notifies your view model, and your view model notifies the view that there are data changes. If you setup your view correctly -- and use XAML rather than code-behinds, it should all come together automatically via the data bindings between the view and the view model.
Regarding sorting: that should be a separate property of your view model that's bound to the sorting property on your view's grid. Your model should maintain the user-set sort, and apply it appropriately to the updated data before it notifies the view model when data is changed.
I'm not sure if unit of work is applicable here since you're not talking about persisting related rows of data to multiple tables and doing so as one transaction -- you're only reading data. I could be wrong though, as I haven't studied unit of work that much.
To address your questions in the comments:
Let's take a step back. Your view model should only be concerned with logic that's related to the presentation of the associated view. It should not have any data access code or code that performs any business logic or domain-related tasks; that code goes in what is collectively called the "model" (forgive me if you already have this, but it's hard to tell exactly where the code you provided in your question resides).
The model can consist of a number of classes that perform different business logic tasks or that represent your domain/entity POCOs (like your entity framework generated classes).
I'm a little unclear what your Channel object is and how it's separate from your entity class/POCO, i.e. the EF-generated model. But again, your interaction with EF and the maintenance and logic related to your entities should happen in the Model.
So yes, the idea would be that you look for data changes in the model using whatever mechanism you want to -- e.g. a timer (btw there are timers that run synchronously, so don't conflate the notion of "timer" with "thread") or binding directly to the "collection changed" event on your collection of entities. When a change is detected, you would simply do whatever business logic is required for that change in the model (like applying transformations, sorting, logging, etc.) and then notify the view model that the change has occurred.

MVVM: ViewModel return instance of a model, or flatten VM List into Model List?

I have a bit of a design issue, and I'm not sure the best approach to take.
I have a list of "Question" models that are loaded in. These questions are presented to the user, and as such are wrapped in a ViewModel class which records the users input.
The input is then used as part of an engine to produce various results. The inputs to this engine are generally lists of models that are used to process the end result.
My issue is that "Question" extends "Action", which is another model that is used in the engine, and it would make sense to make the engine process these objects together. However, the information gained from the user input is currently only kept on the QuestionViewModel.
What is the correct way to deal with this? Is it acceptable to have processes work with a mixture of Models and ViewModels? I have a few suggestions, but I don't know what the best design choice is:
Have QuestionViewModel record the results on Question, and pass a list of Question to the engine.
Pass the list of "QuestionViewModel" to the engine, but return an instance of the underlying "Question" and use that for processing
The purpose of ViewModel classes is to facilitate manipulation of your Model objects via a User Interface.
So typically you will be manipulating a Question instance via the QuestionViewModel interface and then pass the manipulated Question object back to the lower business logic layer (i.e. your processing engine).

Where does formatting logic belong with MVC?

Say my phone number is stored in the database as a 10-digit string:
0000000000
And I want to format this phone number when presenting it to the user as:
(000) 000-0000
And I have an extension method in a utility assembly that handles this formatting:
static string ToPhoneNumber(this string value)
{
return Regex.Replace(value, #"(\d{3})(\d{3})(\d{4})", "($1) $2-$3");
}
My question is, at what point do I apply this conversion?
1) In the view:
#Model.PhoneNumber.ToPhoneNumber()
2) In the view model:
public string FormattedPhoneNumber
{
get
{
return this.PhoneNumber.ToPhoneNumber()
}
}
3) In the controller:
userModel.FormattedPhoneNumber = userModel.PhoneNumber.ToPhoneNumber()
4) In the domain model (same implementation as #2)
5) In the service (same implementation as #3)
Also, does the answer depend whether it's a global formatting need (like phone number) vs. an isolated one-time formatting on a single view?
I would give my thoughts, but don't want to influence any answers.
I personally like to keep things in my ViewModel because what you end up with is strange looking code in your view if you don't. Let's take your example.
Razor View:
#using MyNamespace.Models.Extensions
#model MyNamespace.Models.ViewModels.IndexViewModel
#if (string.IsNullOrWhiteSpace(Model.PhoneNumber) {
<div> #Model.PhoneNumber.ToPhoneNumber() </div>
}
Versus the alternative:
Razor View:
#model MyNamespace.Models.ViewModels.IndexViewModel
#Model.FormattedPhoneNumber
ViewModel :
public string FormattedPhoneNumber {
get {
return PhoneNumber.IsEmpty()
? "Not Available"
: PhoneNumber.ToPhoneNumber();
}
}
You could definitely improve my code, but the point is that it keeps your views simpler and lest cluttered with branching logic.
Also, I never claimed to be a saint, so I don't always follow my own advice, but I should. Do as I say, not as I do :)
I think it is view responsibility to decide how to display data. Because only the view knows what is available for presentation. On the other hand it is probably easier to do it in controller. And controller would know about locale of the user. Over all I think it makes very little difference.
First off, with architectural patterns in general, and especially those dealing with "separation of concerns", the final arbiter is always "what is the best approach in my scenario" - I strongly believe that dogmatic adherence to a set of rules without considering your own plans and needs is a horrible practice. Not to mention the fact there is no clear consensus here: depending on your variety of XYZ (MVC, MVP, MVVM) you'll find opposing thoughts on what goes where all over the internets.
That said, my quick-twitch answer to the question is "Use your judgement".
Arguments for "in the view":
it deals with presentation, therefore it is the views responsibility
Arguments for "in the view model":
generally, the role of the view model is to provide "ready to data bind" representations of the model - hence, transforming model data into a form directly consumable by the view is the responsibility of the view model
Arguments for the model:
this could be an excessively common representation for the model data; therefore, following DRY, the model will assume responsibility for this representation
Arguments for the controller:
... Ok, can't think of a reasonable one here. Controllers typically respond to actions, so it's a stretch to justify it belonging here.
The point I'm trying to make is that so long as a single point of your system accepts and takes on the responsibility and that responsibility is handled solely by that component/layer/class, you've accomplished the primary goal, which is to prevent dilution/repetition/low cohesion.
My personal opinion, fwiw, would probably fall on the view or view model. If this were WPF I'd almost certainly say the view (via the format providers available to wpf data binding). In the web world, I'd probably lean towards the view, although a strong argument for the model exists - say you now want to expose this data via a REST/JSON/etc service: you can easily handle this change (assuming you want to return the formatted data, that is)
TL/DR: It really depends; follow common sense and use your judgement. Just keeping all the related logic in a single place is the important part, and question any dogmatic/commandment-style "Thou Shalt" statements.
It depends on a few things your definition of ViewModel, are you following a (self-coined) MVCVM* approach, where you'd have a ViewModel specific to your view in addition to your domain models?
If so, the VM could certainly contain the formatting logic, that is the whole point of having this View Model in the first place, to Model the View. So Option 2.
That said, the reasoning behind this is that formatting yourself would begin to the DRY principle if you were formatting like this:
#Regex.Replace(Model.PhoneNumber, #"(\d{3})(\d{3})(\d{4})", "($1) $2-$3");
Since you've got an extension method, it's not that much of a problem to call the formatter in your view at all, but I'd still prefer to do it in the dedicated VM.
If your VM is really just the domain model that contains the raw data (see this, pattern 1) then it should definitely be in your View, so Option 1. Just a note, that if you're using this pattern I'd suggest against it as it's making your view strongly coupled against a low-level object, you're better abstracting this out into what you need ensuring that your couplings between Domain Model + View Model are actually strong (ie. compiled at compile time, not runtime!).
Above all - This should certainly not go into your domain model.
* Model, View, Controller, ViewModel. Where the ViewModel contains the data that is to be consumed in your View, in the format of which it requires.
I would place this in the viewmodel and not in the view. The view is intended to just present the data/information to the end-user. Keeping up the separation of concerns makes sure every object is as independent as possible. If you pass the formatted numbers to the view, the view has no concerns about what is to be displayed, just display the formatted numbers.
I would argue that this is modeling, not formatting. If the receiving application needs to re-format the order, spacing or capitalization of these fields it must first split the single field into several separate fields.
This should be the responsibility of the Services layer. We are talking schema, not format. The application requires that the fields be split as part of its data contract. Where this split happens should be in the Application Services layer that your app consumes.
The services layer should try to add metadata to the information through schema.
For example, if I receive a phone number from a data contract like this:
1234567890
The requriements for presentation are as follows:
(123) 456 – 7890
The services tier should be breaking the phone number apart into its elements
<PhoneNumber>
<CountryCode>1</CountryCode>
<Area>123</Area>
<Prefix>456</Prefix>
<LineNumber>7890</LineNumber>
</PhoneNumber>
Option 1 is the best, followed by 2.
In the controller, you should actually remove the formatting to send it to the service layer, so neither the domain model nor the service model are aware of the formatting.

Why don't use repository in the view

I have a partial view that loops through its Model (a list of things) to show the thing.Name and three integer values that are counts of related entities.
First of all, I tried putting: (pseudo-razor)
foreach(thing in Model){
#thing.Name :
#thing.related.entities.where(condition1).Count()
#thing.related.entities.where(condition2).Count()
#thing.related.entities.where(condition3).Count()
}
But its really slow... so I created a function in the ThingRepository that does same queries faster, something like this (pseudo-code)
function GetCountofRelatedEntities(relatedID,condition){
return db.entities.where(relatedID==relatedID && condition).count()
}
and its much faster, so I want to call it. I think I should call it from the controller, but then I need a ViewModel to keep a (thing, int, int, int) collection as the model, or I can use the ViewBag extremely to pass the results to the view, but, and here is the question:
Why not simply use the repository from the view? whats wrong with this code in the view? (pseudo-razor)
#repo=new ThingRepository()
foreach(thing in Model){
#thing.Name :
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
}
Could you tell me why I shouldn't instantiate the repository inside a View? Or I can do it?
Why not simply use the repository from the view?
Because you are violating the MVC design pattern. A view's responsibility is not to fetch data. It is to display data that it is being passed to it from the controller under the form a view model. And it's as simple as that.
You could call repositories or whatever you like in your views but just don't tag your questions with asp.net-mvc anymore because you are no longer doing any MVC. I mean you could do whatever you like - you could even write SQL queries in your view if you want.
But the whole point of the MVC design pattern is to separate the data retrieval logic from the presentation logic.
One purpose of the MVC pattern is to provide a structure that fits a wide range of common programming situations. To simplify:
Model: Describes the shape of your application, i.e. the parts of your software specific to your business.
View: Display the data to the user and transmit user events to the server.
Controller: Acts as a middleman between the view and the model.
What you're proposing "works," in the sense that it gets the data on the page where you want it. In the short term, it appears to be saving you time and effort, as you don't have to bother with controllers, viewbags, etc.
However, you are breaking the MVC structure in a way that you will probably regret later on. For example, say in a few weeks your boss comes to you and says, "Hey, you know that page you added to display that list of entities? We need to do some filtering and sorting on it. And I need it yesterday."
Now you're faced with a choice: Do I add this filtering logic to my view page and meet the deadline, or do I take the time to move the data access code to a controller and rework my view, at the risk of missing the deadline and breaking what's already working?
You'll probably take the easy way out and add the logic to the view, and now you've got a growing mess on your hands. We've been down this road with VB6 and Webforms apps with 6,000-line codebehind files. Trust me--you don't want to go there.
Another problem is that the MVC structure is well understood by the programming community. If someone else comes along and tries to work on your code, you're making it harder for them by deviating from the conventional approach.
The MVC structure is time tested and sound. Until you fully understand its purpose and the benefits it provides, try to follow it closely. It's not a good idea to break the rules until you have a firm grasp on them.
My main objection would be the separation of concerns. Once you start hitting your DB from your view, your "view" really isn't just a view anymore. It's really handy to have a clean separation between your data access and your view.
Why is this separation of concerns important? It makes it easier to work with systems that are composed with these clean separations. When you need to adjust what data is retrieved, you'll never need to fuss with the view. So long as the view gets the right value, it will display it correctly. Likewise, if you want to change how values are displayed, you can modify the view without any chance of borking the data.
The thing is that you should not have any logic in your View because this is not the MVC approach.
MVC is Seperation of concern.
So you should create your ViewModel wich contains ALL the data your View needs.

Adding arbitrary properties to a strongly typed list

I'm looking for a good way to add arbitrary properties to the objects in a strongly typed list, based on the principle that I shouldn't pass a DataTable from my business layer to my presentation layer.
For example, I might have a Category class with the properties CategoryId and Title. On one page I would like to fetch a list of all categories (ie. List<Category>) together with the most expensive product in each category.
A while ago, I would have just returned a DataTable with some additional columns in it with the product data in, but I'm trying not to do that -- it would be trivial to set up it's not good practice.
One option is to add a MostExpensiveProduct property to my Category class, but I might want to display the most recently added product in another case, or the cheapest product, so I'd end up adding a lot of properties to cover all the options. This just doesn't feel right to me.
Am I missing a trick here? What is the best way of doing this? Or should I just be returning a DataTable to which I can add as many columns as I need and not worry about it?
The issue seems to be you have a lot of different views you'd like to offer the user. The options I see are:
You could construct separate classes for each view that inherit from the Category class. Code gen would be a good solution here.
You could store an Attributes property, which has an IDictionary interface, and refer to items by key. I'm becoming a fan of this approach.
You could generate a data table only for binding purposes, for these views... or develop a data table like component where you can refer to fields by Key...
For fields that you compute (say you store sales tax and net price, and compute gross cost), you could store as a method of the Category object, or as an extension method.
I'm sure there are other options that I haven't thought about...
HTH.
You should create a specialized class (a view model) for each view you have containing only the properties you are interested in using in the view. This may seem like unnecessary duplication for the simplest cases, but pays off in terms of consistency and separation of layers. You can construct the view models manually, or if that gets tedious, use an object-object mapping framework like AutoMapper.
There are several things to consider here IMHO. First, it seems that the only reference from Category to Product should be Category.Products, meaning you should never have something like Category.MostExpensiveProdcut etc. As far as your business layer, I would do something like this:
From your code behind in the presentation layer:
call CategoryManager.GetCategories();
call List<Product>ProductManager.GetMostExpensiveProducts(List<Category>);
Now that you have a list of Categories, and a list of Products (assuming your Product has a reference back to its Category) you have all the necessary information to work with. Using this setup your entities (Category, Product) are not polluted.
Another thing to consider is introducing a services layer. If you find that you don't want (for whatever reason) to make two calls to the business managers, rather you want to make a single call and get all your information in one shot I would consider introducing a services layer sometimes aka "application facade". This facade would be responsible for making the individual calls to the business managers and combining results into one response before shipping it back to the UI layer. Someone mentioned that that custom object would be a "ViewModel", which is correct but often used in reference to MVC. Another name for it would be a DTO (Data Transfer Object), which designed for use with service layers/application facade.

Categories

Resources