I am attempting to develop a little program which will communicate with a device on a serial port. The program will be responsible for formatting user entered data and reading and presenting values received by the device. I am pretty new to WPF and MVVM and have achieved a basic understanding of the whole databinding / XAML mess (I think).
Currently my understanding goes something like:
View: UI only stuff. Binds to ViewModel.
ViewModel: Takes a model or various properties of a model and presents them in a way that the View can understand. Also provides a way for the view to modify the model.
Model: The data the UI presents and modifies.
Now I am at a loss as to what provides Models to the ViewModel such that the application as a whole is aware of changes to Models.
The Model currently looks something like the following. My device takes calibration records and can read back all the calibration records.
public class Device : ObservableObject
{
public ObservableCollection<CalibRecord> CalibRecords { get; set; }
private SerialPort sp;
public Device(SerialPort port)
{
this.sp = port;
this.CalibRecords = new ObservableCollection<CalibRecord>();
}
public void WriteCalibration(CalibRecord record)
{
/* Write a calibration record to the device */
}
public void ReadCalibration()
{
/* Read all calibration records from the device and update CalibRecords */
}
}
I am struggling for a place to put this guy so that it can be accessed by the entire application. Currently I instantiated it in the main window's ViewModel but then it can't be accessed by other ViewModels unless I inject it into the constructor. This is fine for a couple classes but gets unwieldy quickly the more classes a ViewModel needs.
Perhaps this is what the so-called "business logic" or "service layer" is. Can you help me understand where to put the business logic in an MVVM app? Or, do you guys have some examples I should look at that focuses on the whole application (particularly the business logic) and not just the MVVM stuff?
Your understanding of MVVM is correct, but the "textbook description" doesn't account for services. Typically this is done with dependency injection (DI). Define an interface, IMyDevice and implement it in a MyDevice class. Then register it with your DI container IMyDevice -> MyDevice. By using a DI container (properly) you'll also take yourself out of the VM construction picture. You would have a VM something like:
public class MyViewModel : ViewModelBase
{
public MyViewModel(IMyDevice myDevice)
{
}
}
to get an instance of the VM, you would do:
theDIContainer.Resolve<MyViewModel>();
and it would new up the MyViewModel class and automatically resolve and pass in the IMyDevice instance for you.
There is a lot more to DI then I covered here... just a basic 10,000 mile high answer to your question. Read up on DI and see how it comes into play with MVVM.
The mindset of MVVM is to separate in a loosely coupled manner layers, allowing each to be modified and tested without interfering with the other.
You test the ViewModel and mock the Models. You test the Models. Your Model may take form of several services automatically injected by some DI container. Subsequently there is as little as possible friction between the Models, the ViewModel. Eventually they may be deployed independently; this lowers maintenance and cost; that's the same mindset of that of microservices.
For instance, you might have a Model that is tested and can be used for a WPF app, mobile app, web app, etc. Your ViewModel however should not a priori be involved in another GUI. You can update your webapp without commit/deploy for the other and the Model; lower cost, lower duration commit-to-deploy (including testing).
When you start with cohesive classes and test them, it will be clear where to put what.
It's OK to have only a View and a ViewModel; though the Model should have the business logic if it's enough rich; you should have tests for the Model, tests for the ViewModel ( behavior of the UI). The VM and the Model layers can be much more complicated than just 2 classes, you may have multiple (automatic) dependency injections (check the excellent Dependency Injection in .NET, Mark Seemann).
Subsequently, logic (for your business) should go in the Model, not in the ViewModel; logic for the UI should go in the VM.
Regarding WPF, the View take the form of a UserControl with View.xaml (what you see) and View.xaml.cs (the code-behind); not all UI logic goes into the ViewModel; pure View logic goes into the code-behind. The code-behind contains in particular all the dependency properties, behavior logic (shared with the xaml code) etc.
Related
I heard its the next best thing in building WPF UIs, but all existing
examples have dozens of lines of code - can I get a Hello World
for MVVM that explains in no uncertain terms what its all about?
I'm fairly new to C#/.net as well, so maybe point me to some
resources that could help too?
Much appreciated!
One sentence explanation:
MVVM is a reimagining of the well loved Model-View-Presenter (MVP) pattern that is designed to work especially well with databinding facilities supplied with WPF to separate application logic from UI design.
Longer, more useful, explanation:
The basic concept of MVVM is the break apart a WPF application into separate components each of which has one responsibility in the process of getting information on screen.
Firstly you have the model. This is a class with very limited functionality that is generally populated from some outside source such as a database or webservice. For example:
public class MessageModel
{
public string Message { get; set; }
}
On top of that you layer the ViewModel, this is where the logic of the application sits, it notifies the view of changes to the model and ensures data consistency. By implementing the INotifyPropertyChanged interface two way databinding between the ViewModel and the view is given for free by WPF:
public class MessageViewModel : INotifyPropertyChanged
{
private MessageModel _model;
public string Message
{
get { return _model.Message; }
set
{
if (_model.Message != value)
{
_model.Message = value;
OnPropertyChanged("Message");
}
}
}
}
Finally you have the View. This is a xaml file that describes the layout of the controls used to display and edit the data in the ViewModel:
<Canvas>
<TextBox Text={"Binding Message"} />
</Canvas>
The reason that you go to all this effort is that the Model is very lightweight and easily passed across domain boundaries. It is simple to send or receive it from a webservice or map it to a database table. The ViewModel, on the other hand is complex, but has few dependencies - it doesn't care where the model gets it's data from, only that it is there and it has no concept of a view at all which makes it very testable (the logic of your application doesn't rely on a UI to test). Finally the xaml is well compartmentalised and can be handed off to a designer who needs to know nothing about the logic of the application, only that the ViewModel will present certain data under certain names. This encapsulation makes it very easy to define roles in large projects, or put together a limited UI to test logic against while the real one is being polished.
MVVM is a star-fan relationship. The fan knows the star but the star does not know the fan. The fan loves his star so much that if the star changes himself ( I mean his dressing style ), the fan changes himself accordingly.
Now replace "star" with "ViewModel" and "fan" with "View" and read it once again.
One sentence? Here goes.
MVVM is a UI segregation pattern where the Xaml (View) binds to a facade (View Model) allowing the guts of your program (Model) to avoid having UI concerns leak down a layer.
The simple statement that helped me get my head around it best was "Could I unit test my business logic without the user interface?" I think this should be the question you ask while learning and designing using MVVM concepts.
This site has a great diagram that explains it.
Basically you have 3 components:
1) Model - The data model of your application. this is pretty standard and the same as any MVP or MVC app.
2) View - The XAML that defines the view/layout of your app.
3) View Model - Because WPF demands that the view attach to things in certain ways (like requires that collections implement INotifyCollectionChanged and stuff like that) it normally requires that you massage your data a little bit to get it in a form suitable for the view to display. This is where the view model codes in. It packages up the data into view models that the view can easily display. This is what your view XAML will bind to. It must respond to events from the model layer and update itself.
(Then your controllers hang on the side somewhere - ideally using WPF commands - and make changes to the model, which fires events to update the view model)
a pattern where the frontend(view) and backend(modal) communicates (back and forth) using a common mediator(view-modal).
The MVVM pattern is when the UI interfaces with an xaml-friendly intermediate object to get at your xaml-unfriendly actual data.
I would say something like: "Presentation pattern for separation of concern between user interface and it's logic"
An improved answer:
MVVM is all about the future; you want to separate your application logic from the framework so that either the framework can evolve, and your app may not have to change, or your app can evolve and you won't have to worry so much about changing the actual UI aspects.
Actually, MVVM is a refinement of a pattern that has been around for some time. I can remember evolving the pattern when I was working in MFC. There are at least two reasons for doing so. MFC or <> is fairly complex, and mixing MFC constructs in with your application logic makes the application kind of brittle. Example: replacing a listbox with a combobox (or selector in modern terms) is much more difficult if the logic for supporting the content of the list/selector is combined with the logic to manipulate list/selector itself.
Some really good one-sentence (or close to it) explanations already. I'll just add to it by saying that if you're past the basic level and you want an example of how to use MVVM in a real-world app that has menus, tool bar, options dialogs, docking tools windows, etc., take a look at SoapBox Core and this demo using SoapBox Core. It is open sourced so you can get lots of ideas.
Because you can't data-bind to your own codebehind
(only half joking here)
I know there's a lot of questions on the topic and I understand how to do it but I need some help on the design of my architecture. I'm using the Simple MVVM Toolkit.
Architecture
I have a ShellVM which is the main VM for my app. It dishes out navigation and props that my main view binds to.
Then I have a ManageVM that does all the grit work for managing the client, stores, imports, exports etc. It also handles navigation of all my management views.
Then I have an ImportVM that fleshes out the importing of data.
I also have a static PageValues dictionary that stores pages and specific properties and values that should be retained when switching views. It also stores any 'global' properties that is used throughout certain VMs.
I'm using Messaging to pass data between the VMs. The validation and prompts (using dialogs) of the PageValues data is controlled in my ManageVM. I placed it here as I feel my ManageVM should handle all 'management' like setting the client and store. Setting the actual values is done by sending a message to the ShellVM that handles this.
The ShellVM handles the CRUD of the PageValues. So in other words, if any VM gets or sets a global/shell-wide property, it does so by means of messaging to the ShellVM. The ShellVM then sends the message/result back to whichever VM requested it.
Question
This feels very spaghetti-like. I've got a ManageVM that does the loading and validations on PageValues that are actually CRUD'ed in the ShellVM.
Am I on the right track or is there any other suggestion I can try to make this feel a bit cleaner?
Thanks for reading.
Edit
What I'm trying to achieve is to have a container that holds values (ie client and store) that could be accessible from multiple VMs. A bonus is to have each page's/view's values in this container too. Then on showing of the view, it will grab its values from the container and populate the view.
You said
if any VM gets or sets a global/shell-wide property, it does so by
means of messaging to the ShellVM
I propose an interface based approach instead of message passing for this purpose. ViewModels passing messages is for view models to communicate,not for setting a global state. If there is a global state of the application,it is better handled through a dedicated service, IMO.
public interface IApplicationService
{
//your applcation methods here
}
public class ApplicationService:IApplicationService
{
}
public class ManageVM
{
public ManageVM(IApplicationService){}
}
public class ShellVM
{
public ShellVM(IApplicationService){}
}
public class SomeOtherVM
{
public SomeOtherVM(IApplicationService){}
}
Yes, this does sound rather messy. You need to try and isolate areas of functionality into their own VMs so they are not dependent on one another.
One of the tricks I use to do this is to try and imagine that I suddenly need to copy a blob of functionality (say one of your pageviews) into another application. How easy would it be? Would it be a case of just copying one VM and injecting a few dependencies? Or is the VM impossibly coupled to the rest of the app?
It's a bit difficult to give advice without knowing exactly what your app is doing, but really you want each PageVM to be in charge of it's own validation, and CRUD. Or, if the data is shared between many pages, then you need to pass in some kind of repository than the PageVMs can query for data. If validation logic is specific to some data, then put it on the model itself and just leave the presentation of that validation to the VM.
For global settings, I tend to pass around a settings object rather than using messaging.
Have a read up on inversion of control, and dependency injection. These can help you to keep objects loosely coupled because you can see exactly what other things your object is depending upon by looking at the constructor. If you are passing in half the application then it can serve as a warning alarm to try and reduce the coupling.
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.
I'm writing a ViewModel-first MVVM application using Caliburn.Micro
My View contains a 3rd party UserControl that implements a Method I want/need to call from the associated ViewModel. How do I do that while still upholding the MVVM principles?
There exists an old thread here on SO where a similar question is asked in a more specific context. I would appreciate it if someone could flesh-out the approaches suggested there a bit.
Approach one suggests that the View could subscribe to an IEventAggregator message. But wouldn't I have to use the code behind file to do that? (I thought that was a big no no in MVVM)
Regarding approach two, I have no idea how to do that. And regarding approach three, thats what I tried first but somehow I didn't quite get it to work.
Let me clarify your understanding:
Yes code in the code-behind is generally avoided, but only because MVVM makes it so easy to bind to viewmodel properties and commands in order to wire up your visual element with the functionality behind the scenes
Code that is view-specific in the code-behind of the view is perfectly acceptable assuming it doesn't cross the boundary of concern. For instance, I have a view in my application that does some visual processing of the page, and to do so I require that there is code in the view. This code may also interact with the viewmodel layer, but it will not directly reference the viewmodel, therefore keeping my components loosely coupled
If you have controls that need particular methods calling, then creating an event aggregator message to propagate the notification to the view is perfectly fine since you are still maintaining the separation of concern between the viewmodel and view (and the application components remain encapsulated and testable)
Example View (I've left all event aggregator wire up code and potential dependency injection stuff out for clarity):
public class MyView : IHandle<SomeNotificationMessageType>
{
// Handler for event aggregator messages of type SomeNotificationMessageType
public void Handle(SomeNotificationMessageType message)
{
// Call a method on one of the page controls
SomePageControl.SomeMethod();
}
}
Obviously, what you wouldn't do is something like this in the ViewModel:
public class MyViewModel : IViewAware
{
public void DoSomethingThatAffectsView()
{
var view = this.GetView() as MyView;
view.SomePageControl.SomeMethod();
}
}
Which violates the MVVM principles since you are tightly coupling MyViewModel and MyView.
What if you wanted to use the Context property in caliburn micro which allows multiple views over the same view model? The code above would break - even if you checked the View type, you would still end up with spaghetti code e.g.
public class MyViewModel : IViewAware
{
public void DoSomethingThatAffectsView()
{
var myview = this.GetView() as MyView;
if(myview != null)
myview.SomePageControl.SomeMethod();
var myotherview = this.GetView() as MyOtherView;
if(myotherview != null)
myotherview.SomePageControl.SomeMethod();
// ad infinitum...
}
}
Of course this is subjective: it may be that your usercontrol affects the viewmodel and the view in a complex way, in which case you might want to consider looking at the architecture and working out how that usercontrol can better fit
Have you got any background on what the UC is and what the method on it does?
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.