Forwarding the DataGrid’s DataContext to its’ columns..
DataContext is a very handy inherited property on any WPF application..
Most of the time, I set DataContext near the root on the [logical] tree, and let the inherited DataContext do its magic to bind the rest of the scene.
I recently tried to bind a DataGridColumn to its inherited DataContext (via its datagrid container) and got a very surprising answer on the output trace window:
“System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element…”
What is happening here?
The Columns collection is just a property in the Datagrid; this collection is not in the logical (or visual) tree, therefore the DataContext is not being inherited, which leads to there being nothing to bind to.
I needed the functionality so I had to create a workaround.. With out much thought I decided to:
- Listen for DataContextChanged in the DataGrid
- When DataContext changes, forward the new value to the DataGridColumns in the datagrid.
- Bind properties on the DataGridColumn to this ‘forwarded’ DataContext ( as I originally intended)
To get it done, I did not inherit from DataGrid and create a new class.. Instead i used the richness of WPF’s property system to pull a 1,2 punch:
- Override DataGrid’s DataContext metadata and listen for changes in it…
- Add a FrameworkElement.DataContextProperty to DataGridColumn …
Code looks like this:
FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridColumn)); FrameworkElement.DataContextProperty.OverrideMetadata ( typeof(DataGrid), new FrameworkPropertyMetadata (null, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnDataContextChanged))); |
The OnDataContextChanged callback simply forwards the DataContext from DataGrid to its columns:
|
That is it. Now we are ready to databind to DataGridColumns.
<dg:DataGridTextColumn Binding="{BindingA}"
Visibility="{Binding ElementName=ShowA,Path=IsChecked ,
Converter={StaticResource BoolToVisConverter}}" />
You can download source code for a small sample from here.
A few more thoughts on DataGridColumn not being in the tree ..
Binding to other UIElements via ElementName will not work because there is no tree.
Binding to a StaticResource works fine..
Binding to x:Static will work fine too.
Happy datagrid coding.. Again, there is source here.
Comments
Anonymous
November 21, 2008
PingBack from http://mstechnews.info/2008/11/forwarding-the-datagrid%e2%80%99s-datacontext-to-its%e2%80%99-columns/Anonymous
November 25, 2008
hey there, Josh also did something similar for this... http://blogs.infragistics.com/blogs/joshs/archive/2008/06/26/data-binding-the-isvisible-property-of-contextualtabgroup.aspx have a look it is really cool....Anonymous
November 25, 2008
The comment has been removedAnonymous
April 07, 2009
Since the release of the WPF DataGrid there have been several common patterns of questions that developers