How to update WPF UI as database changes - c#

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.

Related

MVVM Calculated Fields in Model or ViewModel?

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.

C# WPF MVVM Window OnLoad Binding

My Code behind looks like this...
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
My ViewModel looks like this...
class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
bool flag = Application.Current.MainWindow.IsInitialized;
if (flag)
{
// Do something...
}
}
I guess my question is....Does this conform to the MVVM design pattern? The only other way to do this is How to fire a Command when a window is loaded in wpf
I don't know why, but I don't want to use mvvm-light or any other boilerplate code..
Accessing UI component from ViewModel is violation of MVVM pattern.
Application.Current.MainWindow.IsInitialized is breaking that pattern.
Custom behaviours is more in accordance with MVVM. So, i would suggest to go with the approach you mentioned as link in your question.
Accessing UI component breaks the testability of your ViewModel. How would you write testcase for your ViewModel class? Application.Current will be null when you try to test it via unit test and it will throw null reference exception.
One of the main motive of MVVM was to seperate UI logic from business
logic so that business logic can be tested separately without worrying
about its consumer which is view.
There is no "pure" way to do this in MVVM without boilerplate code. In general, you shouldn't need to do work in response to the VIew within your VM - just the concept is a violation of MVVM, since your ViewModel is trying to do something in response the View, and things should always flow the other way.
The ViewModel shouldn't, in a real scenario, care about the View's state at all - it should be doing nothing but presenting data for data binding by the View.
Most of the time when people are attempting this, it's to try to avoid loading data up front. This is something that's typically handled better by pushing the data to load and starting it directly on a background thread within the ViewModel, then updating the property within the VM when it completes. C# 5's async/await language features can be used to simplify this quite a bit.
While it is generally believed that having some load/unload logic is a pattern violation, there is a set of use cases, where it's necessary. E.g. a view model may need to be subscribe to some events. If it didn't unsubscribe when unloaded, it might not be garbage collected, depending on the nature of the subscription.
What would break the pattern is accessing view state from within the view model, e.g. manipulating controls. The role of the view model is to expose data to the view and managing load/unload behaviour is part of this contract. Knowing when a view model is loaded means knowing when to expose that data.
While it is true the view model should not care about state of the view, it must know how to prepare data for presentation in the view. More importantly the view model is a layer between the model and the view that makes them separate. Yet in other words: since 'model' means logic, then 'view model' means logic of getting data to display. And it is also about knowing when to fetch it/make it available/etc.
You may want to take a look at this blog post, which provides a convenient way of making a view model aware of being loaded. It is not 100% correct in terms of MVVM purity, because it passes FrameworkElement back into the view model, but imagine we ignore this parameter.
The sample code below is based on the above blog post, but with purer signatures. You could implement IViewModel interface on your classes:
public interface IViewModel : INotifyPropertyChanged
{
void Load();
void Unload();
}
Then instruct the view to call adequate methods when loaded or unloaded by using an attached property:
ViewModelBehavior.LoadUnload="True"
Notice the last line has its place in XAML - the view is the one that enforces a certain behaviour, not vice-versa.
What you are currently doing is correct and that is how it is really done with other frameworks behind the scenes.
Since you mentioned MVVM-Light, I suggest you can take a look at caliburn micro. It has very nice framework to conform the MVVM Pattern. Caliburn micro makes it easy to hook up bindings with events on the controls. Just check out its documentation and it is still considered as MVVMy..
in particular because MVVM is mainly used to guarantee easy to maintain and testable code, you should bear in mind that Application.Current will be null if you use the MainViewModel in UnitTests. Therefore this code will end in a NullPointerException in your tests.
You should consider using the Initialized event if you want to ensure that something is initialized already. But you create the ViewModel after you called InitializeComponent - I simply would leave the check out.

MVP: Passive View (with EF) and layers

I'm creating an application using MVP: Passive View and EF (model first). As of know, I have a presenter getting data directly from the DataContext created through EF. It looks something like this:
private void UpdateOrderTableControl()
{
IList<Order> orders = dataContext.Orders.ToList();
IList<OrderViewModel> viewOrders = new List<OrderViewModel>();
foreach (var o in orders)
{
viewOrders.Add(new OrderViewModel()
{
OrderId = o.Id,
CustomerId = o.CustomerId,
LastName = o.Address.LastName,
FirstName = o.Address.FirstName,
Company = o.Address.Company,
Weight = o.Weight,
Sum = o.Sum,
Date = o.Date
});
}
view.GetOrderDataGridView().DataSource = viewOrders;
}
So the presenter gets a list of all orders, creates a list of order view models (combining data from different tables, i.e address above) and then sends the view model list to the view.
It's pretty much the same thing the other way around, when retrieving data from the view in order to edit or add to the db:
private void SaveOrder()
{
GetOrderDataFromView();
if (isNewOrder)
{
dataContext.Orders.Add(selectedOrder);
}
else
{
dataContext.Entry(selectedOrder).State = EntityState.Modified;
}
dataContext.SaveChanges();
isSaved = true;
UpdateOrderTableControl();
}
1) Can EF (the entities created through EF, the DataContext etc) be considered as the DAL? Should it be in a project of its own?
2) I guess the presenter should not have access to the DataContext like that, but rather to another layer in between the two, right? Would that be a service layer, a business layer or both?
3) Is what I refer to as a view model in fact a view model or is it something else? I just want to get my terminology right.
EDIT:
4) I read some suggestions about adding business logic to the entities generated by EF, but that doesn't sound quite right to me. Should I create business objects in a separate business layer on top of EF? Meaning I would have Order (generated by EF), OrderBO (the business object) and OrderViewModel (the order to be displayed). I would have to do more mapping, since I'd add another layer, but it would make the presenter lighter.
Thanks in advance!
Nice questions!
Well, the answer to all of them depeneds on what you plan to do. The first you have to do is to evaluate if the effort needed to implement each pattern is worth the pain.
1)Are you going to switch between different implementations of forms and/or have massive unit tests for the UI alone? Then yes passive view seems a good idea.
2)Is it not so much pain to have a litle code inside the forms? Then MVP supervising controller can be faster to implement.
3)Can most of the logic of your program be inside bussiness layer? After you have all the logic inside BL, how much logic is GUI specific? If it is not that much then code inside the forms with no GUI patterns is the way to go.
About the questions:
1) Yes, EF can be considered a DAL, and doesn't hurt to be in a different project. Since you are into patterns, a usefull pattern here is Repository and Unit of Work Pattern that abstracts EF and lets you unit test the BL. (test without accessing an actual database, with a fake DAL implementation)
2) Depends. EF objects can be considered Data Transfer Objects since they are POCO. DTOs are visible in all layers. Another strategy is to have layer specific objects, mainly in the scenario of a tiered application (each layer in different machine).
If not forced to do otherwise, I would have EF objects visible to all layers but the DataContext itself visible only to BL, not GUI layer. This means that queries and transactions are done in BL but GUI can get the results in the same format.
3) If you follow the above advice, this rather bad object copying isn't needed.
4) This strategy you refer to is the Domain Model (google for more), in which you put logic inside the domain objects, that can also access the database. Again if you follow the advice in 2), this doesn't bother you.
Before getting frustrated around patterns and their correct implementations though, really focus on your needs! The goals are fast delivery and easy maintainance. Too much abstraction can hurt both!
Regarding the question #2, it will be better to differentiate and make some abstractions on Data Access Layer. If you continue keep it inside Presenters, that means your client will ask database each time, load some data and then make some calculations.
If you are working on Client-Server application, it will be better to not mix-up the server logic and client logic. Presenters are definitely on client side, DAL on server-side. You can connect client to server with web services (ex. asmx, wcf).
I see at least three huge reasons to do this:
Ability to write simple unit tests on your presenter without real back-end and server logic
Scale your server side if needed.
You will be able to send less data to client if you make some required calculations on server side
Regarding #3, with passive-view pattern, there is a Presenter, which requesting data (sometimes it called Model), prepare it to display and send to View to render. In Model-View-ViewModel pattern, ViewModel will send request to server and prepare data to display. The difference between MVVM and PassiveView how Presenters and ViewModels are working with View. In PassiveView Presenter will know about View's interface to be able to send data to render. In MVVM View knows about ViewModel and bind data from ViewModel.
The last one, #1. I think yes, it is some Infrastructure layer. If you make an abstraction here, you will be able to move some optimization commands, set loading options (EF is very flexible here) and you will be able to do it quickly.

M-V-VM: What is the best way to handle model data that is generated dynamically from XmlSerialized data

I have both, actual user-generated data and data that depends on it (like the background color of UniformGrid cells that is used to indicate dupe values in the grid, which is calculated each time an INotifyPropertyChanged is fired from the grid's ObservableCollection). There are other such objects that are interdependent in the model. Now when deserialized, depending on the order of the objects in the model class, some dependending objects are updated correctly and some are not. (I come from MFC programming and am used to call UpdateData() after loading a file and set all DDX controls at once.)
The whole thing is quite susceptible to getting buggy on subsequent changes in the code and feels very clumsy. It's like many things with WPF: If you want to acomplish an easy task, it's done in no time. If you want something specific, it gets much more complicated than it should. Is there any good practice how to deal with the problem?
It seems like your main propblem is the correct separation of concerns. WPF & MVVM is quite different from more traditional methods of Windows development.
First up, let's get something sorted here - it might just be a confusion with the terminology, but I'll mention it.
In MVVM the model is not used to store data.
Can it be used to hold data? Yes.
Should it be used to hold data? No.
Holding and transforming the data is the job of the viewmodel. The job of the model is to act as a conduit, it fetches the data (i.e. retrieves from your repository, or controls communication with WCF services, etc). If your model is holding data that means your view will be binding to the model, which is wrong.
Some of the data you talk of should also be held in the view. Determining whether something is a duplicate can be determined in the viewmodel, possibly even in the model (the model could apply business rules and flag data as it passes through). The color to show for the duplicate is a view responsibility - unless that color is determined by business rules, then you can move it to the viewmodel.
You are binding to an ObservableCollection, which infers that you are using a repeater type control like a DataGrid. In this case each row is not aware of any other row. If you fire a property change event from the data object of one row, another row will be totally unaware of it and therefore cannot change how it is rendered based on those changes. In cases like this you must adjust the data of the related row in an observer pattern way.
When you have interdependencies like this, it is normal to wrap each actual data object in another lightweight object that acts as a facade, some people refer to this as having a viewmodel for each row's data object. For example here is a simple Customer object:
public class Customer
{
public string FirstName {get; set;}
public string Surname {get; set;}
}
As you store this in the ObservableCollection in your viewmodel you can wrap it:
public class CustomerWrapper
{
private Customer _customer;
public CustomerWrapper (Customer customer)
{
_customer = customer;
}
public bool HasRelation{get;set;}
public Customer Customer { get {return _customer;}}
}
Now if you want to indicate an interdependency between your Customer objects, for example if they were part of a family, you can simply set the HasRelation property once the CustomerWrapper object has been created:
var myCustomerList = GetMyCustomers();
foreach (var customer in myCustomerList)
{
myObservableCollection.Add(new CustomerWrapper(customer)
{
HasRelation = myCustomerList.Where(p => string.Equals(p.Surname, customer.Surname).Count() > 1)
});
}
Now when you bind your repeater control to the ObservableCollection you can use the HasRelation property to control UI color etc.
Keep in mind that I've kept this is a contrived example and I've kept it simple, I've deliberately missed some stuff out to keep it brief. If your viewmodel subscribes to the property changed event of each Customer object it can then update the CustomerWrapper objects as needed. The interdependency state doesn't need to be stored with the data in the repository because you can determine it each time you display the data. One of the things I ommitted was wrapping the FirstName and Surname proeprties - you could put in a wrapper property for them, or you can simply use the path in your XAML's binding to drill down to the nested object.

Difference between Model and ViewModel

I've never used MVVM before, so I'm probably missing something obvious. When I create a new Panorama application, there's already a ViewModel folder containing ItemViewModel and MainViewModel.
I thought "MainViewModel.cs" is the file that organizes the panorama. However, within MainViewModel, it has this line:
public MainViewModel()
{
this.Items = new ObservableCollection<ItemViewModel>();
}
The ItemViewModel has no interaction with the panorama. These are the then instantiated like this:
this.Items.Add(new ItemViewModel()
{
LineOne = "first line",
LineTwo = "second line",
LineThree = "third line"
});
Why isn't ItemViewModel just a 'Model'? It implements INotifyPropertyChanged, but for what purpose? I would've thought that the ObservableCollection in MainViewModel would be enough to notify any changes, as demonstrated here
Difference is quite simple.
Model holds business logic.
View model contains presentation logic and is additionally shaped to fit views.
In Your case - view model implements INotifyPropertyChanged. That's pure presentation logic.
Model is not responsible for notifying one particular UI that something has changed, it's responsible for transferring invoices, calculating wages etc.
Sometimes (when model is simple) this abstraction is not necessary though.
Some wiki quotes:
Model: as in the classic MVC pattern, the model refers to either
(a) an object model that represents the real state content (an object-oriented approach), or
(b) the data access layer that represents that content (a data-centric approach).
ViewModel: the ViewModel is a “Model of the View” meaning it is an abstraction of the View that also serves in data binding between the View and the Model. It could be seen as a specialized aspect of what would be a Controller (in the MVC pattern) that acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model. The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.
It's the same general concept behind all MV[x] architectures, albeit MVC, MVP or MVVM:
You have the model on the one side, which is basically a software abstraction of your business domain. It does not know and does not care about any UI-related stuff (like e.g. in your case 'notifying the UI about changes'). It implements business logic and that's it.
On the other side you have the UI, with specific needs both in technical terms (e.g. 'WPF wants to bind to an ObservableCollection') and also in terms of user presentation (think e.g. about different date orderings or different decimal signs in different languages).
To cope with this and to be able to clearly separate these requirements in a clean architecture, you need the [x], in your case the ViewModel. It's the only layer within the software that knows both about the UI and the Model. Otherwise, there should be no connection whatsoever between the two.
In your simple example, this might look like overkill, but a normal business software will have dozens or even hundreds of such MV[x] triplets, and you would have no way to maintain a clean architecture without this.
To answer your question: What you have in your example is just a bit of wiring code to set up the described architecture.
HTH!
Thomas
The ObservableCollection will notify when items are added or deleted from the list, but the INotifyPropertyChanged on the ItemViewModel is needed if you want notifications to happen when those properties change.

Categories

Resources