Silverlight DataContextProxy no longer necessary

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}"

2 Responses to Silverlight DataContextProxy no longer necessary

  1. cosier says:

    Thanks Tony, this is really handy!

  2. xtremetabata says:

    I would like to add that DataContextProxy was still relevant until Silverlight 5. Element binding works for binding to controls like combo boxes and listbox etc…, but not for DataGrid column template bindings due to its render timing. With Silverlight 5, we could do Ancestor Binding to find the control we need, but not in Silverlight 4.

Leave a comment