How to move IsSelected for MVVM out of the business objects? - c#

I have a reasonably large application in C#/WPF made with MVVM (sort of).
In listviews I use the IsSelected bindinded to the selected items. These IsSelected property is located in the model of my app, not in a ViewModel.
Currently I only have one viewmodel pointing to one list in the business object (model, not view model), but in the future I possibly want to change this and than the IsSelected property inside the model is not possible anymore (otherwise both ViewModels would have the same selected items).
The selection mode is multiple and can range between 1 to 128 (max length of list) items.
I think it should be inside the viewmodel somehow, but how should I achieve this?

When using MVVM, you are not restricted to a single view model. Yes, you might expose parts of your model from your view model, but you can also expose other view models.
In this case, I'd recommend wrapping the instances of the collection in their own view model and set the binding root for your item templates to that.
For example, if you were data binding to a collection of models, you could pass the instances of each of those models to a view model that wraps the model and then exposes the IsSelected for binding on the view model.

Related

binding wpf data templates to a hierarchy of view models

I have a task as part of a larger story to set some properties in a view to be read-only. These properties are part of a hierarchy of view-models and have been matched to views using data templates from an associated resources dictionary. The data templates follow a very simple style, eg.
<DataTemplate DataType="{ x:Type vm:MyTextFieldViewModel}">
<v:TextFieldView />
</DataTemplate>
Using the example here, the view model MyTextFieldViewModel has a public property in a base class it uses for read-only (ie. IsReadOnly). MyTextFieldViewModel is a child of the parent ViewModel that is being used here.
Is there a way in the data template to bind the IsReadOnly property of the MyTextFieldViewModel to its parent ViewModel? Or can I bind the matching property in the view to something outside of the view model specified in the data template (ie. the IsReadOnly property in the view get bound to the matching property in the parent ViewModel)?
Just to clarify a little - there isn't scope for doing this another way as this will involve a lot of extra work that we cannot justify at this point. If we are going to do anything it's in the Data template. We use Data templates elsewhere that bind ViewModels to controls (eg. to textboxes and comboboxes) where we do something similar to what I'm asking about here.
Thanks in advance for any help you can provide.

MVVM how best to display ListBox.SlectedItem

I have a ListBox bound to a list of ViewModel objects on the LHS of my screen. The ListBox.SlectedItem is bound to a property on my "MainWindowViewModel", called CurrentItem. On the RHS I have a large area that displays the selected item in detail, containing many nested controls for editing and browsing the information the ViewModel contains.
There are two approaches to building the view that I am aware of.
The large area on the RHS is a ContentPresenter with the Content property bound to CurrentItem. In my resources, define a template to be used with my ViewModel object.
The large area on the RHS is a fixed UserControl containing all the required xaml to display the my ViewModel. I bind the DataContext property of my UserControl to CurrentItem.
Which is the nicer approach and why? Perhaps option 2 is better in general but option 1 could be used when there are view models of different types in the ListBox, each with their own template?
Personally I would not bind directly to the selected Object in the ViewModel because doing that you are breaking the MVVM Pattern.
What I would suggest to do is to create a ViewModel for the whole view Including your list of ViewModels and adding a SelectedViewModel Property that is bound to the selected item. So the selection infromation is also in the ViewModel.
Then you can bind the SelectedObject of the "parent" ViewModel to the RHS.
I would suggest reading this MSDN Article for an introduction how to display SelectedItems using the MVVM Pattern.

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)

Caliburn Micro - automatic creation of ViewModel objects from a ItemSource binding of Model classes?

Is it possible in Caliburn Micro to inject a ViewModel object between the view and the model when binding to a collection of model objects?
For example, if I had a IShellViewModel with the following property:
IEnumerable<Foo> Foos { get; set; }
and a ListBox in the ShellView.xaml
<ListBox x:Name="Foos"/>
Which would use FooView to render the listbox items. Can Caliburn inject a collection of IEnumerable for the View to bind to? Or do I have to create a parallel collection of IEnumerable next to the original model's IEnumerable.
I'm not quite sure what you're asking, when you say 'which would use FooView to render the listbox items', do you mean you have 1 view which renders ALL of the items, or a view per item?
If it's the latter, then Caliburn.Micro has a convention where if you have a collection of view models (e.g IEnumerable<FooViewModel>) bound to an ItemsControl, then it will search for a FooView for each of the items and automatically bind the located view to that item's view model.
If you're asking if Caliburn.Micro can autogenerate ViewModel types from your model types, then no. How would it know what properties to expose? Normally a view model reshapes and enhances the functionality of a model, including presentation logic which would be specific to a particular UI technology.

Categories