tags:

views:

511

answers:

5

Using the MVVM-pattern you set the DataContext to a specific ViewModel. Now is there any way to tell the XAML the type of the DataContext so that it will validate my bindings?

Looking for something like the typed viewdata in ASP.NET MVC.

A: 

You can write each individual binding in a strongly-typed way:

<TextBox Text="{Binding Path=(vm:Site.Contact).(vm:Contact.Name)}" />

However this would not validate the fact that TextBox DataContext is of type ViewModel.Site (and I think this is not possible, but I may be wrong).

Andrey Shchekin
A: 

Try this:

<Window>
    <Window.Resources>
        <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
            ...
        </DataTemplate>
    </Window.Resources>

    <ContentPresenter Content="{Binding}" Template="{StaticResource TypedTemplate}" />
</Window>

I haven't tested this code but it should give you the idea. The content presenter will display the current DataContext which will use the DataTemplate. This isn't strongly typed in the compiler but will throw a runtime error immediately on load (in the window's InitializeComponent). You should be able to catch this easily in your testing if something breaks.

Bryan Anderson
.Net 3.5 does not have a DataTemplate.TargetType property
Brian
@Brian You're right, it's DataType. I said it was untested. I updated the answer to fix the error.
Bryan Anderson
+2  A: 

No, the current spec does not have strong typing in Xaml. I believe that with .Net 4.0, Xaml should be seeing the capacity for generics. With that, I would think it should be much easier to have strong typing in Xaml.

dustyburwell
+2  A: 

No. FrameworkElement.DatatContext is the dependency property that enables data binding is of type object.

As pointed out by others, you can specify the expected type of a DataContext for a special template called a DataTemplate. Many controls such as ItemsControl, ControlControl provide access to DataTemplates to allow you to set the visual representation's expectations of the DataContext's type.

Bryan is correct, he did not test his code.

The correct application of a typed DataTemplate looks like this:

<Window>
    <Window.Resources>
        <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
        ...
        </DataTemplate>
    </Window.Resources>
    <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" />
</Window>

ContentPresenter inherits directly from FrameworkElement and does not have a Template property. In addition, the Template property commonly refers to Control.Template of type ControlTemplate which is something entirely different than a DataTemplate.

I think Bryan was thinking of the ContentControl which is one of the two root control types (the other being ItemsControl). ContentControl does in fact inherit from Control. Therefore we can specify the Template property on it if we so choose.

<Window>
   <Window.Resources>
      <DataTemplate x:Key="TypedTemplate" DataType="{x:Type myViewModel}">
      ...
      </DataTemplate>
      <ControlTemplate x:Key="ControlSkin" TargetType="{x:Type ContentControl}">
      ...
      </ControlTemplate>
   </Window.Resources>
   <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TypedTemplate}" Template="{StaticResource ControlSkin}" />
</Window>
markti
A: 

I personally declare a static PropertyPath for each property in my viewmodel the reference this using x:static as the binding path - e.g

public class MyViewModel { public static PropertyPath MyPropertyPath = new PropertyPath("MyProperty"); public bool MyProperty{get; set;} }

xaml : {Binding Path={x:Static local:MyViewModel.MyPropertyPath}}

This way all my bindings get validated on build.

LozH