Add editing to MVVM in a hierarchical data structure - c#

This question is a follow-up of this older one, and it's more of a confirmation than an open question.
My ViewModel instance has a private instance of the Model, _modelInst.
The ViewModel has exclusive access to the Model's data during editing (so the Model doesn't need to implement INotifyPropertyChanged).
Now there are three ways I came up with how to edit the Model data from the View:
Getting/setting directly on the Model instance
e.g. for simple value fields
return _modelInst.fieldname;
_modelInst.fieldname = value;
This one's easy to implement...
Creating a ViewModel instance and operating on the parent's data structure
e.g. for more complex object types like structs:
Creating a new ViewModel for that type.
The ViewModel knows the parent and its fieldname.
displaying that in a ContentControl+DataTemplate
getting / setting:
via methods of the parent with the fieldname as parameter,
overwriting the whole original object even if only one field is changed
This means creating a new interface (with update routines working on _modelInst), implemented by the parent, for each of these structures.
Creating ViewModel instances with no direct knowledge of the parent's data structure
e.g. for (lists of) classes within parent classes
Creating a new ViewModel for each class
Sending update instructions to the parent via
commands
messages
reflection (parent knows which child called the function
by comparing the instance to all stored children)
All of these are a big mess implementing, creating functions for
every field of the model that is editable.
Which means pretty much all fields of the model...
(4.) One could create a generic ViewModel which works via reflection alone, where each
subobject knows its parent and its fieldname (+index, if in a list).
Only the root's logic would then interfere with the model.
But that solution would also require a means to store the path to a field within _modelInst.
Is there any other (more simple) way to achieve this?
Did I misunderstand the principles of MVVM (again)?
Is MVVM suited for manipulation of large hierarchical data structures?

Hopefully these resources will help; they helped me quite a bit as I learned MVVM and how to approach representing object graphs/hierarchies with view models:
Editable Object Adapter
Editable Collection Adapter
MicroModels

This is an excellent question for which I do not feel there is a good answer that comes stock with the MVC pattern.
ViewModels work great when the model they map to has no children.
But when the model has children, as in
Customer
-->Order
-->Country
(imagining Country were a child object of Customer) the design pattern kind of breaks down.
The best thing I've found is to use inheritance and selectively expose
only those children for which you need viewmodel logic. Otherwise, just access
the model's properties of the view that will come in via inheritance.
public class CustomerView : Customer //inherits from Customer (model)
{
public CustomerView(Customer customer)
{
this.FirstName = customer.FirstName
//etc..
//Only if you need it, that is if you have some display-specific
//logic relating to country for a given view, you create
//a CountryView class that inherits from Country and gets populated
//by an instance of it as well
this.CountryView = new CountryView(customer.Country)
}
public CountryView CountryView {get;set;} //sadly you cannot override Country but you may be able to shadow it.
public string DisplayColor
{
if(base.FirstName == "Joe")
{
return "red";
}
return "";
}
}
This gets messy when dealing with grandchildren. If anyone has a better solution, I would love to hear it.
Thanks

Related

Proper MVVM ViewModel and Model pattern

I haven't found an exact answer to this. Some people have mentioned that binding directly to the model as inappropriate for MVVM, however I'm trying to decide if the following pattern still follows MVVM:
View:
<TextBox Text="{Binding InfoForProcessing.BatchId}"/>
<TextBox Text="{Binding InfoForProcessing.BatchStatus}"/>
ViewModel:
private ProcessingTaskModel _infoForProcessing;
public ProcessingTaskModel InfoForProcessing
{
get
{
return _infoForProcessing;
}
private set
{
_infoForProcessing = value;
RaisePropertyChanged();
}
}
....
//doing some processing...then tell Model to populate the data:
InfoForProcessing.ResolveBatchInfo(...);
Model: (Implements INotifyPropertyChanged)
private string _batchId;
public string BatchId //VIEWABLE
{
get
{
return _batchId;
}
private set
{
_batchId = value;
RaisePropertyChanged();
}
}
private string _batchStatus;
public string BatchStatus //VIEWABLE
{
get
{
return _batchStatus;
}
private set
{
_batchStatus = value;
RaisePropertyChanged();
}
}
public bool ResolveBatchInfo(...){
//Get data from Database...
...
//Now Populate Properties with retrieved data (or return false on error)
BatchId = dr[0].ToString();
BatchStatus = dr[1].ToString();
return true;
}
I see another way to do this. I can copy those properties to the ViewModel, bind to them, and have the ViewModel populate them when returned by the Model.
For my current project here, some of the data in the Model is a dependency of queries that will be performed later
I've also made sure to encapsulate as much as possible, and only expose the properties that the View and ViewModel needs to see, while restricting setters as well.
One common stream of thinking is that - for some reason - you cannot bind directly to Model properties in your Views.
However, given that the objective of MVVM is to abstract the UI/View away from the logic, this will not be broken by bindings of this form:
{Binding ViewModel.Model.Property}
This also means you are not copying properties from Model to ViewModel all the time.
Your design, as is, is non-conforming in my opinion, as your data object contains model logic (the ResolveBatchInfo method). Here are two potential solutions:
Have seperate View Model and Model objects. In this scenario, each has their own methods. INPC for the View Model classes and database methods in the Model classes. (as shown here)
Have your POCOs "float" between layers. The important part here is that besides INPC, there is no logic in the objects, they are just data. Under this design, you would have a separate model class that encapsulates data operations and would have a method that returned populated BatchInfo objects.
I usually do (2) in my own projects, as it provides for better seperation of concerns and limits code/data replication.
Of course, with any of the three approaches (my two plus yours) the most important factor is writing code that makes sense not that it is "pure" MVVM. So go with the design that will make your life the easiest down the road.
Personally I don't mind either way, but many people (including the company who I currently work for) believe that wrapping the properties of the model, in the viewmodel is a more 'pure' approach. For me personally though, I think that it's important to think of MVVM as a guide of good practice, rather than a set of rules to be followed absolutely. I've come across instances before where I've been told to forget wrapping the properties of the model, simply because it needed to get done quickly.
Best to list this as bullets
Model DTOs can adhere to INotifyPropertyChange and be binding targets.
The VM should handle any database calls which are initiated from the View and populate stored data on the VM.
I prefer to keep my Models as POCO type entities and not the operation to get the models.
What you describe as your Model is really attributes/properties of a database operation; its status.
Short Answer
All of those items on your model should be moved and done on your VM and bound accordingly.

How to update model and view model in MVVM pattern?

I am struggling to implement MVVM pattern in my current project.
"ClassA" continuously gets required data from a remote device and stores this data inside it's fields. It is a model, I guess. ClassA updates required information via Update method.
"ClassB" continuously gets the data from "ClassA" and stores it in corresponding properties. Looks like it is a view model.
View is a simple MainWindow.xaml with a DataGrid inside.
I have the following questions:
1) How do I update ViewModel?
Should ClassB have an Update method, which accepts an instance of ClassA and updates corresponding fields?
2) Where do I store an instance of ClassA?
Should ClassA be a field of ClassB? If it should, then how do I update Model?
I thought of something like the following:
public void UpdateB()
{
ClassA.UpdateA();
this.FieldOne = ClassA.FieldOne;
this.FieldTwo = ClassA.FieldTwo;
}
4) Does model have it's update method at all or model just stores the data?
3) What do I do inside MainWindow.cs, aside from windows initialization? Do I update view model (ClassB) there?
I find it best to have a object representing an item in each layer of abstraction. This includes the form of the data as it exists on the disk. Remember that in MVVM, the only real goal is to promote loose coupling between the interface(User Interface) and the implementation(ViewModel functionality).
For example, if I have objects stored in XML files, I will have an object in my data access layer that exists only for the proper management of the XML data. Let's call it ObjectXml. This object only contains data in the form that is native to the data on the disk. In this case, all data has a string representation, as in the XML files.
In the model layer, you will have the data representation of the XML file in the expected data types. Let's call this Object. The property getters and setters may access and set the string representation of the data by performing conversions in both directions. This way, the data is ready to be persisted to the data source(xml file, database etc.).
In ObjectViewModel, properties may access those in Object. The viewmodel contains all the members for representing and modifying the model.
Note that ObjectXml is really only beneficial when you are only allowed to store string information, or when a suitable schema does not exist for your data types.
At the end, you have a hierarchy of containment such as the one below:
public class ObjectXml
{
[XmlArray("People"), XmlArrayItem("Person")]
public List<PersonXml> People { get; set; }
//PersonXml is an xml data model similar to this one
[XmlElement("Item")]
public string Items { get; set; }
}
Here is the model for the Xml object:
public class Object
{
private ObjectXml _xmlContext;
public Object(ObjectXml xmlContext)
{
this._xmlContext = xmlContext;
}
public List<Person> People
{
get
{
//Person requires a constructor that takes a PersonXml object in order for this to work properly
return this._xmlContext.People.Select(x => new Person(x)).ToList();
}
set
{
this._xmlContext.People = value.Select(x => new PersonXml(x)).ToList();
}
}
public double Item
{
get { return double.Parse(this._xmlContext.Item); }
set { this._xmlContext.Item = value.ToString(); }
}
}
Obviously, it's not wise to name your class Object as it's a reserved word in C#. Hopefully I've given you some ideas of how to access and update data in a robust and extensible manner.
In short, you don't need an update method at all. Also, short of constants and property backing fields, there are very few reasons to need direct field access in C# MVVM.
See below. Do not listen to people that say the ViewModel and Model need to be decoupled. The main purpose of the model is an intermediary layer that prepares data to be saved or loaded into the program and to store data in a way that is agnostic to both the data and the program functionality(ViewModel)
You do not need an update method. Use properties that access the data model and persist to the data storage(xml, database etc.) if needed.
You do not need an update method.
You should not have to do anything inside of ViewModel.cs. Only code that modifies the view should be in the codebehind. The only ViewModel you should ever access in a view is one that follows the form of MainWindowViewModel, which is more like an ApplicationViewModel that carries instances of other required viewmodels.
Finally, don't get stuck using an overcomplicated MVVM "framework" as most of the functionality is not useful or necessary.
Like stated in Yuris comment, you should not use any update method, but rather implement the INotifyPropertyChanged interface. Like the name says this notifies all subscribers when the value of a certain Property changed.
This is a nice article which contains code to a minimalistic MVVM implementation. If you have trouble implementing the pattern from scratch, try to start with this example and replace the existing classes with your own one-by-one.
As to the update mechanic inside your MainWindow.cs - you don't need any, if you specify the DataBinding in your xaml code like it is done in the example linked above.
I hope this helps you getting started!

Advice on setting up model in a MVVM application using caliburn

I'm new to MVVM so I'm trying to figure out what is the best way to do this. I'm using WPF with Caliburn Micro for this.
I have two different views (each with their view models) for the model I'm trying to manipulate. One view shows the model in a tree view while the other shows a table view of the data.
My model basically looks something like the following
public class Foo
{
public string Name {get;set;}
public string[] Categories {get;set;}
}
The Views are different ways to visualize collections of Foo. The table view is pretty straightforward, but the tree-view will group Foo by the category it contains.
So if an instance of Foo is something like
var fo = new Foo(){Name="one",Categories=new[]{"a","b","c"}};
Then the treeview would be
a
|_ one
b
|_ one
c
|_ one
I have two questions about how to connect the model to the view model in the spirit of MVVM.
What is the best way to populate the viewmodels from the model for the different views? I was thinking something like a singleton FooManager that is accessed from the view models. Or would using the caliburns SimpleContainer be better suited for this?
Lets say I manipulate Foo in the table view by changing it's category collection. How would I propagate the change to the treeview, since that would mean that Foo would appear in a different tree node? Would Foo need to implement PropertyChangedBase' and somehow bubble up the changes to the other ViewModel? Or would it be better forFooManagerto implementPropertyChangedBase`. Seems like the latter would be more reasonable.
TIA
For collections that change reference BindableCollection and are presented on the view.
As for bringing data into a view you can do it through a combination of DI/IoC, via constructor injections on the ViewModel in question. Most of that is done thru Interfaces that can be found in the Container of your choosing either SimpleContainer to MEF if you prefer or what ever IOC/DI container you choose really, the framework is such that can be extended with any container. Going with Interfaces allows for mocking and unit testing of the viewmodels.
Yes bubbling of the change to the View is usually done through what you had though by means of implementing INotifyPropertyChange which is part of the PropertyChangedBase class object.
One thing that will probably rear its ugly head is that Collections based off ObservableCollection don't necessarily bubble the changes of the underlying item's properties in the collection, that is an entirely different thread on SO

Generic View Models?

I am wondering is it good practice to try to make a view that takes in a generic view model?
I am wondering this because someone mentioned that he was anticipating to have to do lots of duplicate code unless he started to make a generic view and generic view model.
So basically the views would be like just a set of controls. One view might have 2 controls(say a text-box and radio button) another view might have 50 controls on it.
They will all have the same look and feel(it just grows by number of controls) . Basically he was thinking having a view model takes in the object(domain object) looks at it and see's 50 fields and renders the right control types.
I guess a edit template could be used to figure out the controls however I am just not sold on a generic view model.
I like generics and they can do very powerful things and in some situations they are good but I am just not overall to crazy about them and try to not use.
I find most of the time it may reduce duplicate code but sometimes it makes the code alot more complicated. Of course this could just because I am still a relatively new to programming and it could be still above my skill level.
The next problem I have with it is I think that view models should be as flat as possible and only expose data that is actually going to be used so people don't start using properties that should never been in the view in the first place.
The next problem I have with it that it could just keep going if you have some complex object that has objects in it that has objects in it. It could go for a long long time.
Personally I avoid using generics in view models. I agree with most of the reasons you mentioned against them and particularly this one:
The next problem I have with it is I
think that view models should be as
flat as possible and only expose data
that is actually going to be used so
people don't start using properties
that should never been in the view in
the first place
The idea behind view models is that they need to be specifically tied to the requirements of a given view, not making them general (/generic) as your domain models are. I prefer duplicating code in view models compared to having some generic monster reused all over the views and partials.
And even in cases where you need to generate dynamic forms and controls you don't need to use generic view models.
So, unless you have some hyper specific scenario (can't think of any at the moment), it's probably a good thing to avoid generics in view models.
This being said, don't rule them out completely, if you feel that there is a situation in which generic view models could be useful don't hesitate to present it here, by explaining the scenario and showing all the code so that we can discuss it.
I don't see anything wrong with generic ViewModels. It is a good way to remove duplication and keep compile-time checks, as opposed to ViewBag.
Example:
Imagine you have a set of Model classes for Product, Category, etc.
Each class (ProductModel, CategoryModel) has an associated display and editor template, which generates appropriate view.
Now you want to construct a set of pages for view and edit.
I usually create a Layout (Master page in web forms) to render the common content (header, footer, menu, etc.)
Then I would create individual, strongly-typed views that accept as model ProductViewModel, CategoryViewModel, etc.
Now we need to define those view model classes. Each view model class should take an instance of ProductModel, CategoryModel, etc (which will be passed to the template). But the layout often requires some additional data (ie. selected menu, logged-in user name, etc). My solution is to create a generic ViewModel that encapsulates this duplicate data for the Layout:
public class EntityViewModel<T>
where T : EntityModel
{
public T Entity { get; set; }
public string UserName { get; set; }
public string SelectedMenu { get; set; }
}
Then you can easily create a ProductViewModel : EntityViewModel<ProductModel>, which contains everything the Layout need to render the page, and you can add there any additional, product-specific data.
As far as ViewModels go, I typically have all of my ViewModels inherit from a BaseViewModel that exposes methods that aid in implementing MVVM. If you'd like to see an example, just comment below.
I really do not like puting business logic inside viewmodel. I think that besides regular properties and error handling inside constructor nothing should be in view model. It makes much cleaner code, and you can more freely make additions to view model.
If you have to much duplicated code you can isolate it to separate viewmodel and then nest it where you need it.
This way you also have only what you need on your view.

MVVM: Should a VM object expose an M object directly, or only through getters delegating to M's getters?

the best way to explain is with example so:
this is the model
public class Person
{
public int age;
public string name;
}
this is the view model
public class PersonVM
{
}
my question is:
should the vm expose the person to the data template or encapsulate the model properties with his own properties?
There is not a general agreement about that question. For example it was one of the open questions about MVVM formulated by Ward Bell here:
Is the VM allowed to offer the V an
unwrapped M-object (e.g., the raw
Employee) ? Or must the M-object’s
properties (if it is even permitted to
have properties!) be exposed
exclusively through the surface of a
VM wrapper?
The principal advantages of not directly exposing the Model in the VM are:
you can use it as a "converter on steroids", formating the model values in a convenient way for the view
you can inject other funcionality related to the user interface, like data validation messages, undo redo,..
The cons are:
you will have to duplicate a lot of code to expose all the models properties in the viewmodel.
if you bind the view control to the viewmodels property, you will send the propertyChanged events from the viewmodel. But what happens if the models property change from other source different from the viewmodel setter? Then it has to notify the viewmodel so you end with 2 OnPropertyChanged, one in the model and one in the viewmodel... quite complex!
So for me the correct answer is: it depends on your requirements.
The view model should declare its own properties and hide the specifics of the model from the view. This gives you the most flexibility, and helps keep view model-type issues from leaking into the model classes. Usually your view model classes encapsulate the model by delegation. For example,
class PersonModel {
public string Name { get; set; }
}
class PersonViewModel {
private PersonModel Person { get; set;}
public string Name { get { return this.Person.Name; } }
public bool IsSelected { get; set; } // example of state exposed by view model
public PersonViewModel(PersonModel person) {
this.Person = person;
}
}
Remember: the model shouldn't know anything about the view model that is consuming it, and the view model shouldn't know anything about the view that is consuming it. The view should know nothing about the models lurking in the background. Thus, encapsulate the model behind properties in the view model.
An interesting solution to this was proposed by Robert McCarter in MSDN volume 25.
http://msdn.microsoft.com/en-us/magazine/ff798279.aspx
He uses a dynamic View Model to provide a layer on top of the Model while avoiding proxying all of the Model properties.
If your problem space doesn't require high performance (dynamics do incur a performance hit), this is an excellent solution. The View does not need to know anything about the Model, but the View Model does not have to proxy properties that are being provided "as is." At any time properties can be added to the View Model to wrap the Model properties without modifying the View or the Model. Read the article for more details.
Having a ViewModel for any Model could be worse than that. What if you have a hierarchical structure of a Model, or even a simple collection?
In that case you'll have to iterate through all models and build a ViewModel instance per-model, and also to register notify-change events or other events. IMHO, this is completely insane, and unreasonable. As DaniCE said, you’ll end up with lot of code and a big headache.

Categories