This one has got me stumped as I THOUGHT I looked at everything but I must be missing something. I have went off the traditional MVVM pattern from the MSDN magazine:
h
Its important to realize when working with WPF that there are two layers: the data layer (DataContext
) and the UI layer (the XAML).
Bindings are used to pull data from the data layer into the View layer.
When you write
<UserControl.DataContext>
<local:DataBoundMVVMChartViewModel/>
</UserControl.DataContext>
You are telling WPF that it should create a new instance of DataBoundMVVMChartViewModel
and use it for the data layer of that UserControl.
When you write
<Label Content="{Binding HelloString}" />
you are telling the Label to look in its data layer (the DataContext
) for a property called "HelloString", and use it for the Content
property.
If the property "HelloString" does not exist in the data layer (which it does not unless you set the DataContext
like you did with <UserControl.DataContext>
), the binding will fail and nothing gets displayed except for a binding error in your output window.
Your DataTemplate
from your ResourceDictionary
is something different from the DataContext
.
In fact, a ResourceDictionary
is just what it sounds like - a dictionary of resources that WPF can use in the application when needed. But objects in the Dictionary are not by default part of the application's UI itself. Instead, they need to be referenced in some way to be used.
But back to your DataTemplate
<DataTemplate DataType="{x:Type vm:DataBoundMVVMChartViewModel}">
<vw:DataBoundMVVMChart/>
</DataTemplate>
WPF uses DataTemplates to know how to draw specific types of objects. In your case, this DataTemplate
is telling WPF that anytime it needs to draw an object of type DataBoundMVVMChartViewModel
, it should do so by using a DataBoundMVVMChart
.
To insert an object into the UI, a Content
property is normally used, such as
MyLabel.Content = new DataBoundMVVMChartViewModel();
or
<ContentControl Content="{Binding SomeDataboundChartViewModelProperty}" />
I actually started out learning MVVM with the exact same article you linked in your question, and had a lot of trouble figuring it out as well, which lead me to doing a little blogging about WPF/MVVM aimed specifically for beginners like me :)
If you're interested, I have a few blog articles about WPF/MVVM that may help you understand the technology better.
What is this "DataContext" you speak of?
A simple MVVM example
As for your actual question:
Preferred method for binding in MVVM, Data Template in Resources file or just DataContext in View itself?
I prefer using a DataTemplate
in the .Resources
somewhere, as then your UI is not specifically tied with one specific DataContext
.
This is especially important when creating re-usable controls with MVVM. For example, if you have a CalculatorUserControl
, and you assigned it a DataContext
in the control itself such as with <UserControl.DataContext>
, then you could never use that CalculatorUserControl
with any other DataContext
other than the one that is created when the control is created.
So typically I set the DataContext
for the entire application once at startup, and use DataTemplates
to tell WPF how to draw the different ViewModels
or Models
in my application.
My entire application exists in the data layer, and the XAML is merely a user-friendly interface to interact with the data layer. (If you want to see a code sample, check out my Simple MVVM Example post)
If you want to use implicit DataTemplates
you have to use the view-model-first approach, you however add a view to your DockPanel
without a view-model as its context. If you simply add the respective view-model (to a ContentControl
or ItemsControl
), the view will be created automatically from the DataTemplate
with the view-model as its DataContext
.
e.g.
<ItemsControl Name="ic"/>
ic.Items.Add(new DataBoundMVVMChartViewModel());
I personally prefer this over view-first (e.g. adding a view which then assigns its own DataContext
), because you usually want references to the view-models, the view is only secondary and manipulated indirectly by interacting with the view-model.