Silverlight DataContextProxy no longer necessary

January 25, 2011

Prior to Silverlight 4, to get access to the Page/Control DataContext from within a grid, it required some trickery to be able to bind elements such as Combobox ItemsSource collections within a grid. Probably the most used idea was to create a DataContextProxy class, and bind to that when you wanted to access the DataContext within a page. Well, this is no longer necessary, so you can remove all references to DataContextProxy classes, and do the following instead.

Note here that I am assuming that you have bound your View Model to the current Page/Control.

Firstly, you need to name your root element. In my case, it’s a navigation page, so I have named it “ThisPage”

<navigation:Page x:Class="MyNamespace.MyClass"
           x:Name="ThisPage"
           Title="My Title"
           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"
           mc:Ignorable="d"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           d:DesignWidth="1085" d:DesignHeight="500"
/>

Of course, I have the data context of this page is bound to my view model (you can do this various ways, even in the XAML)

public MyClass()
{
   InitializeComponent();

   if (viewModel == null)
         viewModel = new MyViewModel();
   this.DataContext = viewModel;
}

Within a grid, I can now bind directly to the DataContext property of ThisPage.

Here I have shown how to bind a ComboBox collection inside an sdk combo box column.

<sdk:DataGridTemplateColumn x:Name="MyListColumn" Header="My Type" Width="150">
   <sdk:DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
         <ComboBox x:Name="MyListComboBox" DisplayMemberPath="Description" SelectedValuePath="Code" SelectedValue="{Binding Path=MyCode}" ItemsSource="{Binding Path=DataContext.MyObservableCollectionInViewModel, ElementName=ThisPage}" />
      </DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>

Note that the ItemsSource is bound to an element, and that element is ThisPage. ThisPage has a DataContext, which is bound to my View Model. So to bind the observable collection I created, called MyObservableCollectionInViewModel, to the ItemsSource of the ComboBox, I need to reference the collection off the DataContext property of ThisPage. Hence the following syntax for the bind itself:

ItemsSource="{Binding Path=DataContext.MyObservableCollectionInViewModel, ElementName=ThisPage}"