I've got what I think is a fairly simple problem in Silverlight, and I'd like to solve it using MVVM principles, largely as a way of enhancing my own understanding.
Let's say I have a simple LOB app that's designed to let me load up and edit a single Employee (just an example, for the sake of explanation). In my example, Employee is made up of a number of complex objects - an Employee has a ContactInfo, a Skillset, an EmploymentHistory, an AwardsEarned, etc. The idea is that I can have this app load up a single employee and get access to a number of different editor screens. Each component of an Employee has its own editor screen.
Visually, the app just ha a left-hand nav bar and a main view on the right side. The nav bar just lets me type in an employee number and load it into memory as the "active" employee. It has a simple list of links - clicking a link should load the appropriate editor screen on the right side.
There are a couple concepts that I don't think I understand well enough, and I'm having trouble proceeding. I know there's always more than one way to skin a cat, especially when it comes to WPF/Silverlight/XAML/MVVM, but I'm having trouble thinking through all the different concepts and their repurcussions.
View-First or ViewModel First
After much thinking about MVVM, what seems most natural to me is the concept of viewmodel composition that Josh Smith seems to promote in his often-quoted article. It seems like the idea here is that you literally model your UI by composing viewmodels together, and then you let the viewmodels render themselves via typed DataTemplates. This feels like a very good separation of concerns to me, and it also makes viewmodel communication very direct and easy to understand.
Of course, Silverlight doesn't have the DataType property on DataTemplates, to many complaints: one, two. Regardless, what I see promoted much more often than viewmodel composition is a more view-first design, where the viewmodel for the view is typically instantiated in the view's XAML or via a DI container, meaning that you can't hand it any parameters. I'm having a really hard time understanding this: how is a ViewModel supposed to serve a Model to a View if I never get to tell it what data is in the model? Reaching through a view to get to its viewmodel doesn't seem to make sense either. I'm very hazy in this area but it seems the accepted answer "use a mediator/lightweight messaging framework." I'm just going through some tutorials now on the messaging system in MVVMLight and I'll be looking at similar stuff, if for nothing else than simply to understand the concepts, but if anyone can shed some light on this I'd very much appreciate it. Anything involving Unity/Prism or MEF is valid, but I haven't gotten that far in my quest for knowledge yet :-)
Instantiating Views and Selecting Them
Theoretically (I say that because SL doesn't support DataTemplate DataType), the viewmodel composition approach could make this very simple. I could have the right side of the screen be a content control whose Content property is bound to a property called ActiveEditor. A parameterized command for the hyperlinks would set ActiveEditor to a given viewmodel.
With a more view-first approach, how would I proceed with this? The first thing that comes to mind is instantiating all of the controls in the XAML of the main view.
Is manipulating the Content property of a ContentControl a good way to go for this kind of situation, or am I better off doing something like setting visibility on each individual control?
The ViewModel (VM) is written so that it is 'wired up' to the Model but has no knowledge at all of the View - in fact, this is what makes it very good to unit test (see NUnit) as it has no idea, and less does it care, whether it is being used by a UI or a Test Framework.
The VM exposes public CLR properties which implement the ICommand interface, the View, having instantiated a VM using (generally speaking anyway) its default constructor, then binds its Buttons/Hyperlinks etc to these Command properties like. So, for example, you may have a VM that exposes a CloseCommand to exit the app, the View may contain a MenuItem that binds to that command, such as:
<MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
Now, the VM would also expose a public ObservableCollection of objects that you want to display in your UI. Whether you populate this ObservableCollection as part of the VM constructor, or whether you do it via a UI interaction (say another Command assigned to a Button click) is up to you but the end result is that you bind a View control to this exposed ObservableCollection in XAML like:
<y:DataGrid ItemsSource="{Binding Breakdown}"/>
or equivelant for whatever control you are using to display the data (not sure off the top of my head what elements a DataGrid has in Silverlight as opposed to WPF).
Meanwhile...: The Mediator pattern is used for VM's to interact with each other, not for the View to interact with the VM. For example, you might have a custom TreeView that has its own VM on the same View as the main chart screen. In this case you could use a Mediator for the TreeView's VM to communicate with the Charts VM.
As for the last bit of your question, I think set up a basic framework using Josh Smith way in the article you mentioned and use that method to add additional ViewModels to the right hand side of your silverlight app.
Hope that helps a bit at least.
Related
I have made a root AppView, a root AppViewModel for my application as a container for all the things. Within the application view, I have a TabControl that each tab has its own task to do. One tab for imoprting data, one tab for issuing, one tab for management and etc:
App_View[Model] // root
{
TabTask1_View[Model], TabTask2_View[Model], TabTask3_View[Model] // tab items
}
1) In MVVM, Is it standard that I have grouped my whole views and view-models into the main application-view and application-model-view ?
2) In MVVM, The model should be implemented for every view & vm ? Or is it standard if I implement the whole models into one or two class files and share the model between them? I personally think that model part is not specific to a certain view, like the class 'student' that can be used anywhere in the code and is not restricted to a certain view. Based on this, if the models are general and shared, yet, is it good to follow the naming convention Class + 'Model' for it? like StudentModel? Is it helpful/necessary to add 'Model' after the general or shared class name like the thing I said?
3) In WPF, What is the best way to implement the Views? I want to edit and design very easily and without any restriction, and it should be standard enough to cover future needs. There are 4 things to use: Window, Page, UserControl and DataTemplate. Which one is the best option that you go for? UserControl or Page?
4) In WPF, How can I load the UserControl/Page(View) inside a tabItem dynamically at run-time based on the MVVM approach?
You're cheating. That's 4 questions!
1)
In terms of how you group your Views and Viewmodels I've seen people put views and viewmodels in the same namespace/folder and others separate them out into different folders based on functionality. The best option for you is what suits you/your team. There is no "right" way.
2)
Keep it DRY - so don't repeat yourself. It is perfectly sensible to reuse code. If you have common classes keep them common. As for naming, the name of the class should be helpful in explaining what it does: I'm sure you'd be able to figure out what the classes NavigationService, NavigationMenuItem and NavigationMenuView did and probably could put together a good mental model of how they relate. So - if naming a class BlahViewModel or BlahModel is useful to you, do it.
3) Implementing views:
A Window is always shown independently. Pages are intended for use in Navigation applications (usually with Back and Forward buttons, e.g. Internet Explorer). Pages must be hosted in a NavigationWindow or a Frame. If you're looking at dynamically adding/removing content, adding content to ItemsControls (TabControl, etc) then you'll want to be creating user controls. You can put user controls in Page and Window object, into other controls, etc, and are really the workhorse for WPF developers.
4)
You have a number of options here:
1)The quick and dirty way is to create DataTemplate which, on being given a ViewModel of type X, load up and apply the ViewModel to their data context. This will allow you to inject a ViewModel directly into a control and have the correct View render.
An example:
View.xaml
<ContentControl Content="{Binding Error, Mode=OneWay}" />
ViewModel:
private void ReceiveError(ErrorViewModel errorModel)
{
//if (errorModel.AcceptCommand==null || errorModel.AcceptCommand is NoOpCommand)
errorModel.AcceptCommand = new DelegateCommand(ClearError);
Error = errorModel;
}
public ErrorViewModel Error
{
get { return _error; }
set
{
_error = value;
_propertyChangedHelper.NotifyPropertyChanged(this, () => Error);
}
}
Styles.Xaml (ResourceDictionary)
<DataTemplate DataType="{x:Type vm:ErrorViewModel}">
<DataTemplate.Resources>
<conv:CustomisableBooleanToVisibilityConverter x:Key="VisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
</DataTemplate.Resources>
<Popup AllowsTransparency="True" PopupAnimation="Fade" Placement="Center" StaysOpen="True"
PlacementTarget="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type v:ModuleView}}}"
IsOpen="True" Width="400" SnapsToDevicePixels="True"/>
So you can see I'm injecting my viewmodel directly into the content control and it's using the data template that is bound to the viewmodel's type to find a View for it.
2)
A better bet is to use a DataTemplateSelector. This basically allows you to specify which templates are available for a control and then uses logic you code to determine which datatemplate to use. You can find an example of this here.
3)
Use a framework that abstracts the UI controls away. Microsoft has a framework (free) that does this called Prism. Basically, instead of adding your usercontrols directly to a TabControl,ItemsControl, etc you add your control to a named "Region". This region is mapped to an underlying control and an adaptor is put in place to manage how that UserContorl is added/removed when you ask it to be. You can find an in-depth discussion of this here. Beware, though, Prism is an application framework so implementing this isn't 3 hours work.
Here is not an answer, it's my experience that i'll explain to you and how I handle with MVVM. I started with WPF 3 month ago and I handle with it.
For each new theme/menue/option I create a new project file wich contains the ViewModels and the Views. All Business classes are collected in one Project file because I may have to use it in more than one ViewModel.
Yes, it was helpful for me as beginner to name the the classes ...ViewModel and ..View. It maked it easy for me to separate the diffrences and also it was/is easier to explain other people your classes ( for example if u have a problem with your coding )
I am using UserControls for our different views and I load them into ContentControls and TabControls without any problems.
Have a look at Prism for MVVM-pattern.
Point 1:
It depends. There are two widely used approaches AFAIK. First is as you've said group all VM's that constitute the same Window with direct dependencies to form a class structure that shows your actual program structure. Second is where you use an EventAggregator(Prism) / Messenger(MVVM Light) to loosely link the VM's instead of direct dependency.
Now both approaches have their benefit's
With the first one It's pretty easy to identify your program structure cos your VM dependencies show it clearly, which is not so clearly visible from the second approach.
Second approach helps you a lot when unit testing VM's cos you are not forced to either mock / work-around all the dependent VM's, It also helps code re-factoring a bit when changing project structure(think of "Plug in" classes)
oh and these ^^ are by no means exclusive. You can mix these together well and fine.
Point 2:
Models do not have any recommended 1 <-> 1 relation with a View / VM like what Views have with VM. Models just hold your Business Logic. I've had apps that sometimes do not hold a Model at all. Something there is just 1 Model used by the entire Application(when the back-end is say a c++ library and you just interface with it with a C++/CLI Module). yes maintain the naming convention to append Model class names with "Model"
Point 3
How about all of them? use them where applicable. Do not take a partial preference to any. When a View composes multiple other sections that are by themselves a View with VM I'd have a DataTemplate with the Data a UserControl. Your app almost always uses a Window and Page is useful for navigation based apps I think. Think Page's are what I've used least tbh.
Point 4
This is a question of tutorial's. Take a bunch of examples, see how it's implemented, reason it and pick your approach. If your using VS2010 get MVVM In the box (It's great. no 2 ways about that. Really hope this could get to be updated for VS2012 if it's not already). For VS2012 check out Two Views MVVM CodeProject which shows the concept, you can then apply it to any ItemsControl of your choosing.
Finally atleast when you're starting up, PLEASE start off with using a MVVM helper library. I prefer MVVM Light <- that link has a couple videos by the author of the library showing some usages and you can find extensive help here on SO about it. If you want to do things yourself, learn the basics from it and then implement it yourself. if you take the high road from day-one it's just a much longer learning curve(Just my opinion)
I'm using MVVM Light toolkit (which I love). I currently have messaging in place for some interaction originating from the ViewModel and intended for consumption by the View. Typically these types of messages indicate the View should do something like hide itself, show a confirmation message that data was saved, etc.
This works. In the constructor for the View, I register with the Messenger:
Messenger.Default.Register<NotificationMessage<PaperNotification>>(this, n => HandlePaperNotification(n));
When I'm using the Messenger to communicate cross-cutting concerns between ViewModels (like identity), I can see that when the ViewModel is cleaned up in the ViewModelLocator, the base class for ViewModels (ViewModelBase) unregisters any subscribed messages. I don't have to do anything, as MVVM Light Toolkit handles that for me. However, when I use them in the Views, I have to expressly unregister them at Closing time, like so:
Messenger.Default.Unregister(this);
I suppose I could implement a base class for Views to inherit from.
However, it strikes me that perhaps this is a code smell to be using the Messenger in the View... it works, but it might not be the best way. I'm wondering if I should instead create a property on the ViewModel and bind whatever part of the View's elements to it. In the example of hiding a form, a property could be a boolean called "Show". As I think about it, I can see that in many cases this will result in having to write a ValueConverter. One way seems less testable. The other way seems to require much more code and perhaps the introduction of excess ValueConverters, which could become a code smell in themselves.
So (after all that build up) my question is this:
Is it preferable to use messages within the View or is it better to add properties (and potentially ValueConverters) to allow the ViewModel to drive it in a more bindable fashion?
In MVVM. ViewModel comunicates with View through DataBinding and Commands. If you need some other functionality, you need to implement it using this means.
Messaging is supposed to be only for ViewModels. Views are supposed to be "stupid" visualisers of your data in ViewModel.
The Messaging logic in MVVM Light is there for communication between ViewModels. I've never run into any communication between View and ViewModel that I couldn't solve with binding and/or commands. Sometimes I need Value Converters and sometimes I need code in the code-behind, but I've never had to make the ViewModel directly push data to the View.
This is an interesting discussion and I found this thread when I was wondering about view model to view communication. Interestingly, MVVMLight's creator seems to find it perfectly acceptable to send messages from a view model to a view. Another example of differing opinions about what is a good MVVM design.
as per my understanding about mvvm is.
there is a model (entity class that also implement inotify...), view (xaml code) and some class as vm (kind of controller which normally inherit icommand) to let us make events/commands to be generated on specific event...
m just wondering about difference between viewmodel class and xaml's code behind class... why don't we simply consider and enhance code behind...
no considerable reason is in my mind to justify this...
or kindly write somethng with example to clear mvvm... and why mvc or mvp is hell for wpf app????
The Model does not implement INotifyPropertyChanged, the ViewModel does. The actual WPF view data-binds to the ViewModel. There is now a lot of documentation online for this.
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
MVVM is identical to Fowler's
Presentation Model, in that both
patterns feature an abstraction of a
View, which contains a View's state
and behavior.
http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx
In practice however, only a small
subset of application UI can be data
bound directly to the Model,
especially if the Model is a
pre-existing class or data schema over
which the application developer has no
control. The Model is very likely to
have a data types that cannot be
mapped directly to controls. The UI
may want to perform complex operations
that must be implemented in code which
doesn't make sense in our strict
definition of the View but are too
specific to be included in the Model
(or didn't come with the pre-existing
model). Finally we need a place to
put view state such as selection or
modes. The ViewModel is responsible
for these tasks. The term means
"Model of a View", and can be thought
of as abstraction of the view, but it
also provides a specialization of the
Model that the View can use for
data-binding. In this latter role the
ViewModel contains data-transformers
that convert Model types into View
types, and it contains Commands the
View can use to interact with the
Model.
MVVM is associated with WPF because WPF's data binding mechanism when combined with this pattern makes testable GUIs a breeze.
Check this two videos to get some idea. Both videos show developing application starting with everything in code behind and then they refactor to MVVM pattern.
Mike Taulty's series of videos (in fact there is 10 videos in total, check at least first and second)
Jason Dolinger on Model-View-ViewModel
Also, see this SO question for more links: MVVM: Tutorial from start to finish?
why don't we simply consider and enhance code behind...
(In addition to what other have already mentioned:) because it make your code easier to read. In the code behind file, you have UI stuff that is impossible or to complicated to do in XAML. In the view model code file, you have everything related to filling your form with data.
As with all design patterns, blindly following it is not the best idea. For very small windows, MVVM might not make sense. For larger windows, MVVM forces you to make a separation of concerns, which will usually make both your code behind file and your MVVM class easier to read, to understand and to debug.
First, for MVVM purposes you don't need the VM to inherit ICommand. Instead, VM contains a set of properties of type inherited from ICommand. So that View just binds to those properties. F.i.:
<Button Command="{Binding DoSomethingCommand}" />
And code-behind isn't used because it's basically inseparable part of the View. It's the same class your View is. You can't easily test it, and your code is often tightly coupled to the XAML.
And Model is not really obliged to (but can) support INotifyPropertyChanged. Whereas ViewModel should of course implement this interface to allow binding.
I suggest you to read a few introducing articles on the subject. It's not that confusing. This can be the first one: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
why don't we simply consider and enhance code behind...
Code behind is often (always?) the simplest approach...if you're a developer. But MVVM is designed to assist more than just a developer. MVVM is for the database girl and the graphics guy too.
Separating M (for the db) and V (for the artist) and VM (for you) allows each person to work independently of each other. So, for example, you don't have to wait for the graphics guy to make a UI before you can wire up the db. You can all work in parallel (in theory).
Separation of concerns means separate jobs.
This will probably be obvious but I can't find the best way.
I want to show the user's ToDo's in a listbox. These ToDo's are in the database and consist of an Id, UserId and Description.
The user logged in to the app.
How can I retrieve the ToDo's for that certain userId and set it up for binding to the listbox?
I was trying with an ObjectDataProvider but I cant figure out how to use that in combination with nonstatic stuff (like my _dbService, userId, language, ...).
Are the only options to make all those things static versus binding in the code behind?
If so, this means that ObjectDataProvider isn't very useful, no?
I find a lot of examples of it being used with a hardcoded parameter but I hardly see any situation where I'd need such a functionality..
I do all my WPF using the Model-View-ViewModel pattern. I've given you one link there but Google will give you loads. MVVM seems to be the standard pattern for WPF. This project is probably more complicated than you need but it is well-written and brings home the use of MVVM.
Basically, you create a Model of your data. In this case, you'd probably create a simple class (I'll call it ToDoItem) with properties Id, UserID and Description. Use your preferred mechanism to get a collection of these from the database. Link to SQL, Entity Framework, a standard query, whatever.
Then you have your ViewModel - you have an instance of the ViewModel for each instance of the Model: the VM has a reference to the M and 'forwards' properties to it. The ViewModel is what you use to manipulate the model.
Then you have your View - this is the UI. You set the DataContext of the View to be the ViewModel and then your bindings automatically bind to the ViewModel. Your View just ends up being the things you can see. All of the work gets done in the ViewModel. This means it's very easy to test.
So, when you click on a button in your View, the bindings pass this onto a Command in your ViewModel which manipulates the Model.
The UI is also a View with a ViewModel. So, your UI VM might load a collection of Models from the database and stick them in an ObservableCollection. The ListBox items collection would be bound to this ObservableCollection.
It's hard to explain all of this in a post like this. Read a couple of articles and see what you think. I'm still quite new at this, too, but I believe my reading about MVVM has paid off.
Hela Thomas, Tom here from Orbit One :)
MVVM is the way to go. I'm on my 4th project and WPF really shines if you use mvvm. You already tried MVC (or MVP as we did on recy*tyre) and that's a nice separation of concern.
MVVM takes it a step further since the viewmodel knows absolutely nothing about the view.
The view binds to the viewmodel, so it has a reference to it (2 way, super powerful and works beyond the typical MS demo). The viewmodel is just a poco and is a representation of your view, data + behaviour. Once you dig this paragraph the cool term mvvm will have no secrets.
I see if I can come up with a small demo. Maybe I'll have time later.
What I will come up with is a view (xaml, file 1) that binds to a viewmodel (file 2, a poco class, not to be mistaken with code behind). The model can be whatever you like (service layer or directly to the repositories). Using the power of 2 way binding we will bind to an observable collection meaning that if we add/delete/... something to the collection the view will pick it up without us putting energy into it.
My first 2 wpf projects was done with Caliburn Micro (see codeplex) which is a powerful framework based on conventions. It shields you away from hardcore wpf (creating tour dependency properties yourself mainly) and you can create something relatively fast without fully understanding wpf. That's a downside of itself but it worked for me. As of project 3 I started taming those dependency properties myself and it will make you a better wpf developer.
I see the question is from October.. did you find a good solution?
Over at the StackOverflow question How can WPF Converters be used in an MVVM pattern? I've learned that Value Converters should not be used in the MVVM pattern since the functionality of a Value Converter should be handled by the ViewModel itself.
This makes sense.
But I remember reading that you should not expose XAML elements to the View, but instead expose only collections of data which the View then binds and displays using DataTemplates.
However, converters seem quite powerful (e.g. as they are used in the MVVM Template demo, see the "Messenger Sample" after unpacking it) in that they can convert objects to objects, e.g. Message objects to FlowDocument objects, or Customer objects into Visibility objects, or custom Status objects into Images, etc.
So if a ViewModel is going to take on the functionality of a Value Converter, it is going to have to expose XAML elements and properties such as StackPanel, Visibility, Color, FlowDocument, etc., right?
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Because then that limits the ViewModel to be used only with a specific visual representation.
Once you have the ViewModel emitting XAML, it puts design content into a developer's domain.
This means that the designer using Expression Blend cannot edit design assets - and the designer/developer workflow is broken.
Keeping the XAML on the page and using Value converters with data templating keeps the design separated from the code.
When your ViewModel exposes specific XAML it also limits that ViewModel to be used only in that specific instance and makes it less reusable.
Don't forget that you can use DataTemplates too. I can see some sense in keeping ValueConverters out of MVVM, but DataTemplates are all about transforming objects into GUI.
Your ViewModel can expose other objects (e.g. nested ViewModels) to the GUI, and the GUI can use <DataTemplate DataType="{x:Type SubViewModel}">... to map those objects to GUI.
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Absolutely, because it undermines all the goals of MVVM:
You're no longer unit testable, at least not easily.
You no longer have separation between logic (view model) and presentation (view). Thus, designers and developers cannot easily collaborate.
Code maintenance is more difficult because you've mixed the concerns together.
If I saw a view model returning a view, I wouldn't even classify it as MVVM.
I think one idea of mvvm/mvc/mvp etc. is to isolate the GUI code to one file/class.
If you do this can you change to some other UI without rewriting the other objects?
I think if you're passing around WPF specific objects the answer is no.
It's a value judgment you'll have to make for your self.
There is no absolute 100% rule that works for this or many other concepts when you discuss them without the perspective of why the community's mind has shifted as it has in this direction. There is no 'assumed' truth or science in 'conventional wisdom' regardless of how new or compelling it is at the time.
In other words - just do the best with your team as if your good, your already getting pulled down far more in human concerns than anything as real as this.