1

I'm currently getting started with XAML and I have a question regarding how to define the DataContext of an element.

I've created a View that includes a Page with the following markup:

<Page x:Class="View.MainView"
  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"
  xmlns:ViewModel="clr-namespace:ViewModel"
  mc:Ignorable="d"
  Title="MainView">
  ...
  </Page>

When I want to give this Page a DataContext to be used by child elements, this works:

<Page x:Class="View.MainView"
  ...
  mc:Ignorable="d"
  Title="MainView">
  <Page.DataContext>
    <ViewModel:MainViewModel />
  </Page.DataContext>
  ...
  </Page>

And this doesn't:

<Page x:Class="View.MainView"
  ...
  mc:Ignorable="d"
  Title="MainView" DataContext="ViewModel:MainViewModel">
  ...
  </Page>

For me, it looks like the Page element expects the DataSource to be defined as a XAML property and not as an attribute. However, the IntelliSense in Visual Studio offers me a DataContext attribute for the Page, so I guess I'm just using a wrong syntax here. Can you point that out to me?

Thanks!

GeorgDangl
  • 2,146
  • 1
  • 29
  • 37
  • I am guessing here but the first example requires an instance, where as the second doesn't seem to instantiate one. – JWP Feb 24 '15 at 15:20
  • There is nothing in my code behind on the View. With debugging, I found that the (working) example calls the parameterless public constructor of my ViewModel class. – GeorgDangl Feb 24 '15 at 15:25
  • 2
    `DataContext="ViewModel:MainViewModel"` only assigns the string "ViewModel:MainViewModel" to the DataContext property. It does not (and is not supposed to) create an instance of the MainViewModel class. Please refer to the [XAML Syntax In Detail](https://msdn.microsoft.com/en-us/library/ms788723.aspx) article on MSDN. – Clemens Feb 24 '15 at 15:29

1 Answers1

4

You can use the attribute to specify the DataContext, but you should consider how does your viewmodel get instantiated.

Using a property in this way

<Page.DataContext>
     <ViewModel:MainViewModel />
</Page.DataContext>

you tell WPF to instantiate the MainViewModel and to assign the created object to the DataContext property of the Page.

With an attribute, you just specify a string in that case:

DataContext="ViewModel:MainViewModel"

But you want WPF to create an instance for you.

So you can use e.g. a Binding or a StaticResource / DynamicResource to assign a created instance to the DataContext property:

DataContext="{Binding ViewModel}"

or

<Page DataContext="{StaticResource ViewModel}">
    <Page.Resources>
        <ViewModel:MainViewModel x:Key = "ViewModel"/>
    </Page.Resources>
</Page>
dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • Thank you, this is a good explanation. If I understand it correctly, in any View I use, I will have to instantiate an object of my view model and then bind to it in the XAMLs child elements? – GeorgDangl Feb 24 '15 at 16:49
  • 1
    @Rosenheimer, not really. Your viewmodel can be created first (e. g. by another viewmodel), and WPF will then create a view for it and automagically attach the viewmodel to that view (see `DataTemplate`). You can create your viewmodel in code behind (e. g. in the view's constructor) and assign it to the `DataContext` property of your view. You can inject your viewmodel in the view using an IoC container. There are so many ways to create a viewmodel and attach it to the view's `DataContext` property. I would suggest you to read more about it. – dymanoid Feb 24 '15 at 22:14