I have a ListView and the ItemTemplate of the ListView contains a TextBox. The ItemSource of the ListView is an ObservableCollection of type T of which the Viewmodel has an instance of as Property. The View needs to bind itself to a particular Property of T. (with T existing out of multiple Properties)
<ListView ItemSource={Binding SomeObservableCollectionOfTypeT}>
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text = {Binding T.Someproperty, UpdateSourceTrigger=PropertyChanged} />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
At first I had T as an inner class inside the ViewModel (with T also implementing INotifyPropertyChanged) but I realised I needed this class in multiple ViewModels in an identical fashion. T would be the model here.
I'm inclined to avoid using INotifyPropertyChanged in the Model as I think it is desirable having the View bind to the Viewmodel exclusively.
Is this the exact scenario where using INotifyPropertyChanged is valid in Models?
How should I approach this situation in a typical situation like this, where you need to bind to Properties of a Type that is inside a collection in your ViewModel using the MVVM Design pattern?
I'm inclined to avoid using INotifyPropertyChanged in the Model as I think it is desirable having the View bind to the Viewmodel exclusively.
It depends on how you define a "model". If it's some kind of domain object that is used across several applications, you should not bind directly against it but instead create a wrapper view model class that does implement INotifyPropertyChanged.
Is this the exact scenario where using INotifyPropertyChanged is valid in Models?
Certainly as long as the "model" is not a domain object. Then you should replace it with a view model in your client application.
How should I approach this situation in a typical situation like this, where you need to bind to Properties of a Type that is inside a collection in your ViewModel using the MVVM Design pattern?
Create a "child" view model class that implements INotifyPropertyChanged and translate the current model objects to this type, for example by simply wrapping the properties.
Related
I've been recently trying to re-write a WinForm application to WPF. I've been trying to implement an MVVM structure into my application because it's starting to look a lot like Winforms where I need to name my controls x:Name and referencing them all the time. Essentially, I'm not using the power of what MVVM provides.
One thing I'm having trouble wrapping my head around, is the Window. Every time I create a Window, it generates a partial class. My question is, how does that tie in to MVVM? The confusion starts as to what content this class should contain. Does it have a single DataContext binding? What about button events?
From my understanding (at the moment), is that this "partial" class should have very minimal code, perhaps only to bind your ViewModel in your constructor:
this.DataContext = new ViewModel();
and the rest of the functionality should come from your ViewModel with the help of binding things on XAML. However, each ViewModel should be tied to a single Model. But what happens when this particular Window calls for many Models, such as a Client, Products, etc? Do you make a single ViewModel class that somehow does everything?
The essence of my question lies within the contents of this particual "partial" class and its relation to the ViewModel.
Looks like you've got two questions:
How the heck does this partial class thing fit in with MVVM?
How do I structure all the view models and models and stuff?
1) What you are referring to as a "partial class" is often called "code-behind" when discussing WPF. This is because in that in non MVVM patterns it usually has all the actual C# code that sits behind the xaml layout - i.e. "code-behind".
You're correct that a good indication of a good MVVM implementation is minimal/no code-behind. As you mentioned, usually all it will have is binding the DataContext to the ViewModel - and in lots of frameworks this is all handled for you and you don't even need that. In my MVVM projects every partial class looks like this:
namespace MyApp.Views
{
public partial class GeneratorView : CreatableView
{
public GeneratorView()
{
InitializeComponent();
}
}
}
Part of the nice thing with MVVM is that all the spaghetti event updating/connection code that you had to have in WinForms is all bypassed by using bindings. But as you noted, you can still do this with WPF but it's generally considered bad practice, and definitely with MVVM.
With all content and commands being bound directly to the ViewModel through data binding, the partial class need not have any content at all. There's lots of interpretations, but on a basic level:
The View lays things out and shows things on the screen.
The View Model contains UI specific data and logic. It deals with commands from the view, and may utilize business services.
The Model represents your data. Think of the stuff that's going in a database or file system.
2) MVVM is not strict in how you structure it. Generally the convention is you have ViewModel for every View. However, I believe it's fine to have a ViewModel without a View. Especially simple ones.
But what happens when this particular Window calls for many Models, such as a Client, Products, etc? Do you make a single ViewModel class that somehow does everything?
Not at all, it seems like you've got this all-or-nothing monolithic ViewModel in your head. If these were really simple structures, I'd do it like this:
However, you might want a dedicated ClientView or ProductView, and instead embed them in the main view:
The key thing is your ViewModels may contains other ViewModels, arrays of ViewModels. Similarly, your View can embed other View's to display it's ViewModels - or not. If they're simple, or you're just, say, listing a few properties (Maybe when you click an 'info' button a dialog shows up and that has the full View for said ViewModel, but in the list you just want the Name and Cost.
It's flexible. On thing is, often the Window isn't even part of the MVVM pattern. It's so "dumb" that it doesn't even have a ViewModel (also, what if you want to embed your app into another app or something?).
It's more flexible to have a high-level "AppViewModel" and all your Window does is contain that (often not even bothering with a WindowViewModel, it's not really a concern).
You can use more than one model in a view model. The aim of the view model is to abstract from the business layer (models, services).
For creating and keeping the instances you may use IoC (Inversion of Control) containers. There are many IoC containers available to use in .NET applications such as Castle Windsor, Autofac and so on (see List of .NET Dependency Injection Containers (IOC)). You just need to instantiate a view model object by necessary model objects, for example like this:
public class ViewModel
{
private readonly IClientModel _clientModel;
private readonly IProductModel _productModel;
public ViewModel(IClientModel clientModel, IProductModel productModel)
{
_clientModel = clientModel;
_productModel = productModel;
}
// Logic of your view model
}
Also you need to configure object dependencies and scopes (your model will be a singleton or a new instance of the type). The container injects dependencies when it creates the objects.
Also I recommend to read the article MVVM - IOC Containers and MVVM.
Yes, the way I approach it anyway, is to keep my Window dumb. How dumb? I guess it depends on the application. If I am just trying to throw a proof of concept or something with low importance together then I will cut a few corners. If I am working an a large application that will need to be maintained then I am going to be more strict, I may even frown on setting the ViewModel from the constructor in that case.
However, each ViewModel should be tied to a single Model
I don't know that I agree with that. That is not how I have approached MVVM, anyway. I would say that every View should be tied to a ViewModel. Within the ViewModel it may be the case that you are only dealing with one model but I have also had great success using a single ViewModel to expose multiple models to a View in a coherent way as well.
Here is an example of a template I use as a jumping off point in some of my smaller projects. I like to use explicit ViewModel properties in my Window and Views but you don't have to; you could modify this to use the DataContext property instead.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public object ViewModel
{
get { return (object)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel",
typeof(object),
typeof(MainWindow));
}
In the code behind the ViewModel propoerty is just a dependency property of the Window. I will bind the Window content to this property. In this case it is an object but it could be some base ViewModel class or an interface if you want.
In my Window's markup I add a DataTemplate for each ViewModel to the Window's resources. If everything is wired together correctly WPF's implicit data templating will take over and make sure the correct view is rendered whenever the ViewModel property is changed.
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:Example.ViewModels;assembly=Example"
xmlns:views="clr-namespace:Example.Views;assembly=Example">
<Window.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModels:FirstViewModel}">
<views:FirstView ViewModel="{Binding }" />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:SecondViewModel}">
<views:SecondView ViewModel="{Binding }" />
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ContentControl HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{Binding ViewModel, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
</Grid>
</Window>
I have a very general question and I'm not quite sure if this one has asked/answered before.
I have a Model (Workflow) in my application. Currently I'm assigning the Model to the DataContext of my window / view, but actually I want to create a ViewModel around the Workflow and assign this ViewModel to the DataContext.
The problem is, that the window and views are created using DataTemplates and lists where only the model is assigned, since everything is created in the remote backend. The front-end gets the information about the model which is associated automatically in the DataContext when view is created.
Of course I can create the ViewModel manually when the DataContext is set. But then I need to change the DataContext and set it to the ViewModel and the old DataContext is gone. Besides I have to do it manually although it could be easily done in XAML using a resource.
Is there a pattern that copes with this requirement? I haven't found anything.
Thanks
Martin
You can simply add a DataTemplate into a particular view's Resources section:
<DataTemplate DataType="{x:Type ViewModels:YourViewModel}">
<Views:YourView />
</DataTemplate>
In this particular case, the YourView view will be rendered whenever an object of type YourViewModel is found in the UI and the view model will implicitly be set as the YourView.DataContext property value. Using this DataTemplate, you can display the YourView view like this:
<ContentControl Content="{Binding PropertyOfTypeOfYourViewModel}" />
Note that this DataTemplate should be declared in a Resources section outside of the YourView view and in scope of the ContentControl.
Introduction
I have an application that imports lab instrument data while it is running. This data is imported and then displayed in a ListView at an interval set by the end-user as per his or her testing requirements. When a value of interest appears in this ListView that they watch, they then press a Start button and the application begins performing calculations on that datum and subsequent data until a Stop button is pressed. So on the left side of the screen is a View for displaying the imported data and on the right side is another View for watching the values and statistics as they are calculated and displayed.
The Current Code
The View that displays the ListView where data is imported to is the ImportProcessView.xaml and it sets its DataContext to the ImportProcessViewModel.cs. The VM I've just introduced has a property ObservableCollection<IrData> that the ListView, I've also just described, binds to. Now to the interesting part...
The ImportProcessView has a ContentControl that sets it's content dynamically a UserControl representing the controls and fields specific to the type of Phase that is chosen by the end-user.
<StackPanel Background="White" Margin="5">
<ContentControl Content="{Binding CurrentPhaseView}"/>
</StackPanel>
There are three PhaseViews, each in its own User Control and each sets it's DataContext to the ImportProcessViewModel. As a result I am getting some severe VM bloat to the tune of 2000 lines. Ridiculous. I know. The reason for the bloat is because the ImporProcessViewModel is maintaining state through properties for each of the three PhaseViews and not only that but contains methods for performing calculations whose data is stored and displayed in these "PhaseViews".
What I am trying to achieve
Obviously before the ImportProcessViewModel becomes more unwieldy, I need to break it up so that each PhaseView has its own ViewModel, but also such that each ViewModel maintains a relationship back to the ImportProcessViewModel for sake of the dependency imposed by the ObservableCollection of IrData.
R&D
I've done my research on ViewModels communicating with each other, but most of the results involve applications that were written with a specific MVVM framework. I am not using a framework, and at this point in the project it would be too late to refactor it to start using one.
I did, however, find this article and the answer offered by 'hbarck' suggests something simple like composition to achieve the result I want, but since I don't have much experience with DataTemplates I don't understand what is meant when he/she suggests exposing "the UserControl's ViewModel as a property on the main ViewModel, and bind a ContentControl to this property, which would then instantiate the View (i.e. the UserControl) through a DataTemplate"
Specifically, I don't understand what is meant by "bind a ContentControl to this property which would then instantiate the View through a DataTemplate".
Can someone clarify by way of an code example what is meant by instantiating a view through a DataTemplate in the context of this example?
Additionally, is this a good approach (as suggested by 'hbarck')?
As one can see, I am already setting the Content property of a ContentControl to the Phase View that is to be instantiated. I just don't know know what involving a DataTemplate would look like.
I don't understand what is meant when he/she suggests exposing "the
UserControl's ViewModel as a property on the main ViewModel, and bind
a ContentControl to this property, which would then instantiate the
View (i.e. the UserControl) through a DataTemplate"
A DataTemplate allows you to specify a relationship between a view (such as a user control) and a view model.
<DataTemplate DataType="{x:Type myApp:MyViewModel}">
<myApp:MyUserControl />
</DataTemplate>
This tells a ContentPresenter to display MyUserControl whenever its content property is set to an instance of MyViewModel. The view model will be used as the user controls DataContext. Typically, the DataTemplate is added to your application resources.
What the author of that answer is saying is that you could have a viewModel that has a property of another viewModel type which is bound to the Content property of the ContentPresenter.
<ContentPresenter Content="{Binding ParentViewModel.ChildViewModelProperty}"/>
Providing you have a DataTemplate that specifies a relationship between your ChildViewModel and your user control, WPF will automatically load the user control into your view.
This answer I provided to another question might also provide you with some help.
I need to break it up so that each PhaseView has its own ViewModel,
but also such that each ViewModel maintains a relationship back to the
ImportProcessViewModel.
This will allow you to break your viewModels into smaller, more manageable viewModels that look after themselves. This will leave you with the problem of communicating between the viewModels.
If you nest your viewModels as suggested, then your child viewModels could expose events that the parent viewModel can bind to so it is notified when something changes. Something like this:
public class ParentViewModel // Derive from some viewModel base that implements INPC
{
public ParentViewModel()
{
childViewModel = new ChildViewModel();
childViewModel.SomeEvent += someEventHandler;
// Don't forget to un-subscribe from the event at some point...
}
private void SomeEventHandler(object sender, MyArgs args)
{
// Update your calculations from here...
}
}
This is simple and doesn't require any additional frameworks. Some might argue against this method but it is a valid solution that works. The downside is that the viewModels have to know about each others existence in order to subscribe to the events so can end up being tightly-coupled. You can use standard object-oriented design principles to get around this though (I.E. derive your child viewModel from an interface so that the parent only knows about the interface and not the implementation).
If you really want to go for loosely-coupled communication then you need to use some sort of event aggregation or message bus system. This is similar to the above method except there is an object that sits between the view models and acts as a mediator so that the viewModels do not have to know of each others existence. My answer here provides some more information.
There are pre-existing solutions available but this would involve taking on an additional framework. I would advise using Josh Smiths MVVM foundation as it is very simple and you would only need to use a single class anyway.
While Benjamin's answer is really elaborate and very helpful, I'd like to clarify how what I wrote in the other post would apply to your problem:
You'd have three different PhaseViewModel-Classes for your different phases, probably derived from one common base class, let's say PhaseVMBase.
Instead of a CurrentPhaseView property, you'd probably have a CurrentPhaseVM property. This would be of type Object or PhaseVMBase, and return one of the three PhaseViewModel classes, depending on what the user chose in the main ViewModel.
PhaseVMBase would have an UpdateData method, which would be called by the main ViewModel whenever it received new data that should be processed by the phase view. The main ViewModel would call this method on whatever happened to be the CurrentPhaseVM at the moment. The PhaseViewModels would implement INotifyPropertyChanged, so that changes as a result of UpdateData would be visible to bound controls.
Your DataTemplates would be declared in the resources of the main view, e.g. the main window,
like this:
<DataTemplate DataType="{x:Type my:Phase1VM}">
<my:Phase1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:Phase2VM}">
<my:Phase2View/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:Phase3VM}">
<my:Phase3View/>
</DataTemplate>
Notice that there is no x:Key, only the DataType value. If declared like this, WPF would choose the appropriate DataTemplate when asked to display an object of type Phase1VM, Phase2VM or Phase3VM, respectively. Phase1View, Phase2View and Phase3View would be UserControls which would know how to display the different ViewModels. They wouldn't instantiate their ViewModels themselves, but expect that their DataContext is set to an instance of their respective ViewModel from outside.
Under the assumption that the ContentControl which should show the phase view is declared in the main view, and that the DataContext there would be the main ViewModel, you'd declare the ContentControl like this:
<ContentControl Content="{Binding CurrentPhaseVM}"/>
Depending on the actual type of CurrentPhaseVM, this will choose one of the three DataTemplates, and display the appropriate UserControl. The UserControl's DataContext would automatically be the ContentControl's Content, since that would the object which caused the DataTemplate to be chosen.
EDIT: Lists and code formatting don't go together, it seems...
Recently, I have been trying to implement the MVVM design pattern, but I encountered 2 problems which I can't solve:
As I see it, I must use ObservableCollection in my Model classes, in order to pass it in the ModelView to the View. I hope that I wrong, because the View must not affect the Model structure, and I shouldn't be limited to this specific collection type.
Is there any way to do two-way binding with a value-type item list?
Example:
public ObservableCollection<bool> MyBooleans
{
get { return m_booleans; }
}
<ListView ItemsSource="{Binding MyBooleans}" ...>
<ItemTemplate>
...
<CheckBox IsChecked="{Binding}" ... />
...
</ItemTemplate>
</ListView>
Your view model should expose collections which change (i.e. have items added / removed) as ObservableCollections (or some other class that implements INotifyCollectionChanged). This does not mean your model needs to expose collection that implement this interface.
Your view model is effectively an adapter on your model that makes it more readily bindable. As an example, if your application displays tweets, your service layer might return a model which is a list of tweets. Your view model would then insert these into an observable collection, resulting in your view being updated. You could then retrieve new tweets via your service at some point in the future (using a timer), these again would be returned as a list. Your view model would then add these tweets to its ObservableCollection resulting in the new items being visible in the view.
The point of M-V-VM as we all know is about speraration of concerns. In patterns like MVVM, MVC or MVP, the main purpose is to decouple the View from the Data thereby building more flexible components. I'll demonstrate first a very common scenario found in many WPF apps, and then I'll make my point:
Say we have some StockQuote application that streams a bunch of quotes and displays them on screen. Typically, you'd have this:
StockQuote.cs : (Model)
public class StockQuote
{
public string Symbol { get; set; }
public double Price { get; set; }
}
StockQuoteViewModel.cs : (ViewModel)
public class StockQuoteViewModel
{
private ObservableCollection<StockQuote> _quotes = new ObservableCollection<StockQuote>();
public ObservableCollection<StockQuote> Quotes
{
get
{
return _quotes;
}
}
}
StockQuoteView.xaml (View)
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.DataContext>
<local:StockQuoteViewModel/>
</Window.DataContext>
<Window.Resources>
<DataTemplate x:Key="listBoxDateTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Symbol}"/>
<TextBlock Text="{Binding Price}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource listBoxDateTemplate}" ItemsSource="{Binding Quotes}"/>
</Grid>
</Window>
And then you'd have some kind of service that would feed the ObservableCollection with new StockQuotes.
My question is this: In this type of scenario, the StockQuote is considered the Model, and we're exposing that to the View through the ViewModel's ObservableCollection. Which basically means, our View has knowledge of the Model. Doesn't that violate the whole paradigm of M-V-VM? Or am I missing something here....?
I'm more familiar with MVC than MVVM, but it's generally accepted that the View will have knowledge of the Model. As long as the Model has no knowledge of the View this is okay.
If this really is a concern for whatever reason, check out the "Passive View" design, where the View knows nothing more than the raw data fed to it.
In MVVM the view model is something in between the view and the model which exposes data from the model in a way that can be handled easily by the view. In a strict MVVM application the view does not know about the model, only about the view model.
In your concrete example the view model should not be called StockQuoteViewModel but StockQuotesViewModel (be aware of the plural) because the view model is exposing many stock quotes by a specific ui collection which is easy to handle by the view (because ObservableCollection<T> implements INotifyCollectionChanged<T>). The type of items in the collection should be a view model (e.g. StockQuoteViewModel) which exposes data from a single StockQuote object. In such a view model you can add logic like adding a $-symbol to Price and so on.
It is often easier to expose some model objects in a view model, but the correct way would be to create a view model for each model class.
Best Regards,
Oliver Hanappi
No. You are not exposing StockQuote. You are only specifying an (loosely typed) interface in the view. The view knows only two properties: Symbol and Price. You can easily replace StockQuote with anything else as long as it implements those.
Check video: Jason Dolinger on MVVM. It will answer your question.
Also, see SO question wpf mvvm confusion for additional resources.
My understanding is that ViewModels are to Models as Properties are to Fields. This is a very loose analogy, but it does imply you're not properly insulated if your View is directly accessing your Model. Just as with trivial properties in a class wrapping private fields, you end up with a lot of duplication and boilerplate code when wrapping relevant Model properties in ViewModel properties for consumption by the View. This is something that bothers me with this pattern and I'm still not decided on whether the benefits are worth the bloat.
In this particular example, I think it would be overkill to create a VM for each StockQuote instance, as you're likely not doing any significant logic for the View that represents an individual StockQuote. I think it's much cleaner and more maintainable in these small cases to simply bind to the Model class directly. Creating a VM for the small case would reduce coupling, but it would also increase complexity and I think it's a case-by-case judgment call as to whether this is beneficial.
Maybe I have this wrong but isn't the idea of the viewmodel to encapsulate the model completely. For instance you have stock quotes exposed to the view but they should be mapped to properties native to the viewmodel which would then be binded to. This is to necessitate "cleaning" that might be needed during the transfer of data to the model/view.
That way the view only ever knows the viewmodel. It also means that if the model was not legacy it could be implemented as an interface and further reduce the coupling between the viewmodel.