I have been told the best approach to setting DataContext for views in MVVM is to use the DataTemplate. So I am trying to have the DataContext of MainWindow set to an instance of MainWindowViewModel by using a DataTemplate.
I have not been able to figure out how.
I have tried putting the ResourceDictionary in various places (in the App.xaml, in the Window.Resources tag...)
I have googled to no avail. Here's what I have... (it doesn't work but, here it is)
App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataTemplateTesting" >
<DataTemplate DataType="{x:Type local:MainViewModel}">
<local:MainWindow/>
</DataTemplate>
</ResourceDictionary>
MainViewModel.cs
namespace DataTemplateTesting
{
public class MainViewModel
{
public MainViewModel() { }
}
}
The only other thing I did was add a handler to MainWindow for the DataContextChanged event so I could see if it ever fired... it doesn't.
Any ideas how to fix this??
EDIT: Not that there is anything here that can't be generated, but... here's the MainWindow code.
MainWindow.xaml
<Window x:Class="DataTemplateTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataTemplateTesting"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContextChanged="Window_DataContextChanged" >
<Grid>
</Grid>
</Window>
MainWindow.xaml.cs
namespace DataTemplateTesting
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
int i = 10; //This line exists solely to put a debug stop on.
}
}
}
<DataTemplate DataType="{x:Type local:MainViewModel}">
<local:MainWindow/>
</DataTemplate>
First, this statement does not mean "Create a MainWindow
and set its DataContext
to MainViewModel
". It actually means whenever you see a MainViewModel
just put MainWindow
in the visual tree.
Second you cannot add a Window
class as a child to another Visual
. If you try you will get an exception Window must be the root of the tree. Cannot add Window as a child of Visual
.
The correct way to do it is like this:
<Window x:Class="DataTemplateTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataTemplateTesting"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl>
<ContentControl.Content>
<local:MainViewModel/>
</ContentControl>
</ContentControl>
</Grid>
Define this in the resource dictionary:
<DataTemplate DataType="{x:Type local:MainViewModel}">
<local:SomeUserControl/>
</DataTemplate>
and create a user control:
<UserControl x:Class="DataTemplateTesting.SomeUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox/>
</Grid>
</UserControl>
This is useful if your content changes dynamically or you are defining ItemTemplate
of a view. Otherwise just set the DataContext
of Window
manually.
<Window x:Class="DataTemplateTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataTemplateTesting"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel>
</Window.DataContext>
<Grid>
</Grid>