WPF data binding cancel operation - c#

I have some controls which are bound to individual domain objects. I have to implement some basic update operations to the database via those objects. I'm using MVVM Command binding to update database. The problem is the Cancel button which basically reloads the original values. I have temporarily made it reload the objects from database, but have to change it soon.
Deep copying and manually syncing the objects didn't work since the objects don't allow easy cloning.
Setting UpdateSourceTrigger to Explicit of Binding and calling UpdateSource manually seem to be the best solution, but couldn't find a way to implement it, since I don't have direct access to view controls from view model (or command)
Any ideas ?

I remember using this article when struggling with the UpdateSourceTrigger Explicit.
Later I had the same problem (I needed access to the view Controls). That was when I discovered that View Model is not something to maintain the state of the WPF View, but also a way to present the data and in this case your data is are some entities hydrated from the database.
I would have something like this:
[WPF View Model -> Entity View Model] -> Entity VM to Entity translation -> Database.
Inestead of this in your ViewModel:
public ObservableCollection<MyEntity> MyEntities
Have this:
public ObservableCollection<MyEntityViewModel> MyEntities
Where MyEntityViewModel is a VM of my Entity
Let me explain a little more: The WPF View Model should present the data wrapped in VM. This is for presentation purposes. What happend if you have a quite complex demographic object graph but you only need to display Name, Birth Date and Blood Quantum ? Its far more easy to create a view model object to wrap those three properties than navigate the object graph. That's why tools like automapper exists.
What is the benefit of all this?
You don't need to fake the object graph to do your tests
You don't tie you entities to the ViewModel. If you cancel, you don't need to do a re get or something like that. you are not touching the enties except when validation succeeds.
Of course, this maybe doesn't fit all scenarios, and maybe you can think of something in between.
HTH

Related

Correct approach to MVVM

I'm trying to understand what's the best way to work with a viewmodel and with the model that stays behind.
My model is a collection of custom items (like a list of user configurations).
I understand that the correct way to expose this model is through a ConfigurationListViewModel that converts the model's list in data readable by the ui.
But how should I manage the items that lies behind the ConfigurationListViewModel?
Should the single configuration itself have a ConfigurationViewModel?
Or the main ConfigurationListViewModel should handle the exposure of its items?
If I want to add a Configuration to my ConfigurationList, I call an Add() method to my ConfigurationListViewModel, and it creates in itself a new Configuration, or should I create a new (Configuration? ConfigurationViewModel?) in the parent, and then call an Add([Configuration?ConfigurationViewModel?]newConf)?
Really, the answer is any of the above.
If the data used in the view model has a form identical to that of the model, you aren't doing yourself any favors by creating a ConfigurationViewModel class that is just a copy of the Configuration class.
As to adding, you can do it either way. Sometimes you want to do all your editing in the view model so you can "revert" the changes by not actually modifying the model. If that's not a concern, modifying the model first and propagating to the view model is just as valid of an approach.
All that being said, none of your approaches will violate MVVM. Pick what makes the most sense, especially semantically and for future maintenance. In general, I prefer simplicity to blind adherence to a principle such as "every data object needs a view model representation".
In my experience the ConfigurationListViewModel containing an ObservableCollection<ConfigurationViewModel> is the best (most flexible and cleanest) way.
Just for displaying selected items differently than non-selected items, it's useful when the items know about their selected state. And because selection is nothing the model should care about, you need a ConfigurationViewModel with an IsSelected property.
Updates (add, delete items) of the list (if triggered by the user/UI) should be done mainly by the model. (It's the model's responsibility to know how new item are initialized, for example.) And the ListViewModel should then change accordingly: create a viewmodel from the newly created model item or delete the viewmodel whose item was deleted in the model.

MVVM Correct using of the pattern

I just want to know if i'm doing it right. I have a mainview (MainView) with it's viewmodel (MainWindowViewModel). In the MainView there is a button to call another view (SubView). The SubView hast also a ViewModel (SubViewModel). After the SubView is closed through it's viewmodel i want to access a property in the subviewmodel from the mainviewmodel.
The code to call the subview from the mainviewmodel and access the property looks like:
private void SubViewExecute(object parameter)
{
SubView sub = new SubView();
bool? result = sub .ShowDialog();
if (!result.HasValue || !result.Value) return;
if (sub.DataContext is SubViewModel)
{
SubViewModel subViewModel = (sub.DataContext as SubViewModel);
string property = subViewModel.Property;
}
}
Am I doing the mvvm-pattern correct, or is there a better way to achieve want i want?
To your core question: "Am I doing the mvvm-pattern correct, or is there a better way to achieve want i want?"
No, you aren't adherring to the core principle of MVVM correctly, and there is a better way to achieve what you want (if I understand what you want correctly).
First, MVVM comes from a need to make all layers testable without requiring knowledge of the layer "above." For instance, your application should be able to technically do everything it's supposed to through just the Model; it should be ableo to retrieve, update, and create data as needed - even if this data is not presented in a user intuitive manner, yet.
Second, your applicaiton should then be able to technically do everything that the User would want it to do through the View-Model, but without any kind of UI. So you should be able to "look" at your data and perform the various program functions, like Saving.
Then, when you throw your view on top, all you need is data-binding and event handling, and you are good to go! (mostly)...
Mainly, it is the View's responsibility to correctly manage it's own DataContext from the ViewModel; it is not the ViewModel's job to push a datacontext onto a particular View. Another way to look at it is, the View accesses methods and properties in the ViewModel to cary out the work requested by the user in the user interface.
So, I would start by flipping your code around, so that the View controls which views are active at any given time, and that each view is ware of it's own data context, and methods to utilize them.
(Now, before the SO community jumps on me about not saying anything about the VM first approach - here it is. You could try a VM first approach, but it is more difficult to understand at first, and you are going to want to use a framework to help you, like Caliburn.Micro or MVVMLite or something)
So, for View First, what you want to do is have the MainView know how to populate itself with SubViews. It's the job of the MainView to ensure that it's data context is the correct MainViewModel, as each SubView is created in the MainView, the MainView will ensure that each SubView has the correct SubViewModel instance set as it's data context.
This should be logically easy to approach because your MainViewModel already contains a set of SubViewModels (of various kinds) inside.
Hope that helps get you going, if you have more specific code questions (with sample code) we can help you futher.
It's not entirely clear what you want here - but this is definitely violating MVVM in a purist sense.
Your MainViewModel, in this example, needs direct knowledge of the View layer (SubView), which is typically avoided whenever possible.
However, the best approach to avoid this depends a lot on whether you're using a framework (many frameworks have tooling for matching a View to a ViewModel, and displaying dialogs, etc), which framework, and whether you're working View-first or ViewModel-first.

How does validating and saving data in WPF MVVM work right?

I am new to MVVM (and a bit of WPF) and I've read many Code Project articles, blog posts and Stackoverflow questions in the last few days. I have the impression that data binding works really nice to display data once loaded from a data source (database) and to keep the model in sync with the view, also updating all other appearances of the model data in the view(s).
But I still have no real clue how saving, and before that validating, is supposed to work right. I have a strong Windows Forms and ADO.NET background. I am well familiar with coding both the database access layer and the view updating. Back then, you had temporary, scratch data, being edited, only in the view, and the last saved version of the data in the model classes and the database. The model classes were usually in sync with the database. It was the view that contained the data that was not saved yet.
You also had a Save button that would read all data from the controls, validate it in code and either accept and save it to the model and database, or not update the model and display an error message instead. In case of an error, the user input remained in the UI for the user to correct it. But no other part of the application could see it. And you had a Cancel button that would just throw away that part of the view that contains the editing controls - the model was still valid and unchanged.
Now with data binding and ViewModels just exposing data from the Model classes, what is entered in a TextBox immediately goes into the model, be it correct or not. IDataErrorInfo is nothing more than that - informational. You can regard it or ignore it. The only hard validation that is enforced is type conversion: you can never update a non-numeric string into a numeric model field. But that's about it. I'm going to solve that by letting the ViewModel do all validation and throw an exception from the property setter on invalid data. This is the only way to implement the known behaviour.
But where does saving and discarding of data go? When will I actually write data back to the database? Does every leaving of a TextBox cause a database write so that I won't need an explicit Save command anymore (and only get reverting through Undo)? When will I validate a whole record of data? How will I deal with the model and database being out of sync, with invalid input immediately propagating through the whole application and all views thanks to data binding? When and how can I discard any user input with a Cancel button, leaving the model unchanged - or reverting it to a state before that editor dialog was opened?
I feel like MVVM does not provide solutions to these elementary problems. Did I just miss them or do they really not exist? If MVVM is not a solution to this, then what is? Or should MVVM better not be used for data editing applications in WPF?
MVVM doesn't answer these problems for you - you have the flexibility (power? burden?) to resolve database writing in any fashion you choose. If you need to collect all the data before you save back to the database, you can do that - just add a Save button bound to a SaveCommand on the ViewModel, which executes your data access stored procedure/entity framework update method/whatever. If you want to record each bit of data individually, then you'll need to call the data access procedures somewhere else (probably the property setters on the view model?)
Essentially, MVVM is not a complete end-to-end software pattern. It is only looking at the communication between what the user sees (listboxes, textboxes and buttons) and the application itself. Your data access code, serialisation, storage, persistance, whatever you are using and however you are using it is all held behind the MVVM side of the application, in your application code (the model). You can write this however you like.
I'm currently writing an application where a user fills out a form and hits Save or Cancel. Save and Cancel are both buttons bound to commands on the ViewModel. In the ViewModel constructor, the properties of a model object are copied to the properties of the ViewModel. On Save, the properties of the ViewModel are copied back to the model's properties and the data access code is initiated. On Cancel, the model's properties are copied back over the ViewModel's properties.
class MyViewModel
{
public MyViewModel(MyModel model)
{
this.Name = model.Name;
this.Colour = model.Colour;
}
public string Name {get;set;}
public string Colour {get;set;}
// commands here that connect to the following methods
public void Save()
{
model.Name = this.Name;
model.Colour = this.Colour;
model.SaveToDatabase();
}
public void Cancel()
{
this.Name = model.Name;
this.Colour = model.Colour;
}
}
That's a simple way to do it - of course, you need to throw in INotifyPropertyChanged and the rest of it, and there are other options. But I find this method easy to understand what is going on and a good base to add anything else that you may need to chuck in.
With MVVM, you bind controls in your view to properties and commands in your ViewModel. The Model represents your database.
Validation of user input can be done in several ways. You can restrict textboxes to only accept certain data, you can validate data in property setters etc etc.
I'm no database expert, but I would collect the information in my VM and add a save button somewhere in the view which validates data and writes it to the database. A cancel button could overwrite the VM properties with the (unchanged) values from the model (database).
(edit: what Pete says :)
I think you are confusing ViewModel with database, your view is binded to an object in the ViewModel, when leaving a TextBox, whatever in the TextBox will be assigned to the object of ViewModel, which is still in memory. You will need a save button, MVVM is just a pattern to separate traditional view and code behind for decoupling and easy unit testing. You still need to perform data validation after save button is clicked. For discard user input and revert to previous state, you could either save your ViewModel data before editing, or use Entity Framework to track and manage data changes.

How to get changes from the model into the modelview?

I'm currently busy with rewriting an application into MVVM (in stages, because it is a lot of work).
Currently I can fill listviews and controls depending on changes in the model view and also listview selections are coupled correctly (at least I know how I can do it correctly).
However, I was wondering about changes in the model to be reflected in the modelview (and thus in the view). Should I add INotifyPropertyChange interfaces on all items in the model and subscribe on the modelview (maybe even like a chain if I want to subscribe to an item that is not in the 'top' of the model hierarchy)?
E.g. I have a list A containing a list B etc. Do I need to subscribe in list A for property changes of list B and in the model view subscribe to list A? And unsubscribe if another list selection is made (resulting in a lot of unsubscribe and new subscribe items)?
Thanks for reading/answering.
Yes, typically you would implement INotifyPropertyChanged on your models, and subscribe in your view models. If you are using a framework such as CSLA for your business entities, then Rocky describes an anemic vs rich model, where in the later you expose the model directly to the view on your view model as a property.
I think INotifyPropertyChanged is a stable dependency, so it doesn't pollute your models significantly. Some people do not like exposing the model directly to the view, but I find it saves a lot or repeat code. You may find that if you don't, your view models end up duplicating many of the properties on your model, without adding any value.
If I understand right, you want to programmatically change your data in the model and show the updated data via the viewmodel accordingly?
I would suggest you change the viewmodel properties in your code instead and only use the models for loading/saving the data, that would eliminate that problem.

MVVM and where to keep displayed fields/properties

I am learning MVVM by building a simple WPF calculator app.
In this simple app, there is one view (Main window), one ViewModel, and one Model (the calculation engine).
My calculator displays the current value of all previous operations, and the operations that got to that value.
For example a display might look like this:
1 * 2 * 3
6
I am wondering if these should be saved as Properties on the ViewModel, Model, or both?
More general -- should the ViewModel contain only properties that exist on the Model, or this is not mandatory?
In this case i would save a CurrentValue and DisplayValue properties, just wondering which architecture layer should these belong to.
In MVVM, ViewModels allow you to shape multiple entities from one or more data models or sources into a single object, optimized for consumption and rendering by the view. The below image illustrates the concept of a ViewModel:
The purpose of a ViewModel is for the view to have a single object to render, alleviating the need for UI logic code in the view that would otherwise be necessary. This means the only responsibility, or concern, of the view is to render that single ViewModel object, aiding in a cleaner separation of concerns (SoC). Concerns are distinct aspects of the application that have a particular purpose (i.e., concern), and keeping these aspects apart means your application is more organized, and the code more focused. Putting data manipulation code in its own location away from the view and controller, enforces SoC.
Using ViewModels in MVNM for finer granularity and better SoC leads to more easily maintainable and testable code. Remember, unit testing is about testing small units.
I am wondering if these should be saved as Properties on the ViewModel, Model, or both?
In my opinion these should be property in ViewModel. Why these should be in the Model too? There is no benefit I can think of having this in Model too. These properties will only make sense to user in View so they should be displayed via ViewModel in the View. Model has nothing to do with it. At most you will have to pass expression 1 * 2 * 3 to Model and get results back, as you mentioned your engine is in Model.
More general -- should the ViewModel contain only properties that exist on the Model, or this is not mandatory?
In general, a ViewModel should contain all the properties that have to be displayed in the View (via ViewModel). Regardless of the fact whether this property exists in Model or not. There is no rule that if this exists in ViwModel it should must be in Model too and vice versa. Generally Model is nothing more than representation of your business entities.
First of all, the model is not the place, where all your logic should be. The model is just the data for the view.
View model should contain any code needed to correctly adapt the model data to WPF display.
In your case you should work on an architecture a bit more.
There should be a class like CalculatorProcessor. View model may have properties for CurrentExpression, that, when a button = is pressed, are passed to a CalculatorProcessor to get processed (calculated) in sequece.
A result is also a property on a view model class that a view's controls are bound to.
ViewModel is specifically created for databinding purposes and as you expected contains properties needed by the view. In my opinion if you need any computed values to be displayed in the view, you can expose them as properties on view model.
A model class is not only a business object, even if the model classes typically provide property and collection change notification events through change notification interfaces, so they can be data bound in the view, you can define an observable collection of instances of a class representing operations that represent he Ui interaction, so when a new op is inserted by the user, you add it to the collection and the UI will automatically reflect it through the binding to an templated listbox (for example)

Categories