The importance of the position of Window.Resources element in WPF XAML markup
October 05, 2011
Got burnt by a little gotcha today writing a sample Windows Presentation Foundation (WPF) application. I was manually hooking up a WPF DataGrid
control to a Entity Framework data source that was defined in another project, through a combination of XAML and code-behind.
I had declared the DataGrid control as follows in Window.xaml
:
<DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding Source={StaticResource AlbumsSource}}" Name="AlbumsDataGrid" Margin="5" RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1"> <DataGrid.Columns> <DataGridTextColumn x:Name="IdColumn" Binding="{Binding Path=Id}" Header="Id" Visibility="Hidden" /> <DataGridTextColumn x:Name="NameColumn" Binding="{Binding Path=Name}" Header="Album Name" Width="\*" /> </DataGrid.Columns> </DataGrid>
in which
... ItemsSource="{Binding Source={StaticResource AlbumsSource}}"
is responsible for binding the items to the data grid. I had set a collection of resources on Window
that I was below the DataGrid
as follows:
<Window.Resources> <CollectionViewSource x:Key="AlbumsSource"></CollectionViewSource> </Window.Resources>\
Then I set the data source of the CollectionViewSource
I’d defined in Window.Resource
in the code-behind as follows, in the Window_Loaded
event handler:
private void Window\_Loaded(object sender, RoutedEventArgs e) {//look up AlbumsSource in resource dictionaryCollectionViewSource src = ((CollectionViewSource)Resources\["AlbumsSource"\]); using (var ent = new MusicTrackerContainer()) { src.Source = ent.Albums; } }```csWhere `MusicTrackerContainer` is simply a Entity Framework model. This did not work as expected, instead throwing an `XmlParseException` stating 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.'.[![](images/xmlparseexception-for-static-resource.png "xmlparseexception for static resource")](http://www.paulkiddie.com/wp-content/uploads/2011/10/xmlparseexception-for-static-resource.png)To fix this, the `Window.Resources` element should be declared in the XAML **before** it is referenced in the `Binding`. I moved the `Window.Resource` element to be the first child of the `Window` element and it worked. XAML follows:```xml<Window x:Class="MusicTracker.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Loaded="Window\_Loaded"> <Window.Resources> <CollectionViewSource x:Key="AlbumsSource"></CollectionViewSource> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="\*" /> <RowDefinition Height="\*" /> </Grid.RowDefinitions> <DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding Source={StaticResource AlbumsSource}}" Name="AlbumsDataGrid" Margin="5" RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1"> <DataGrid.Columns> <DataGridTextColumn x:Name="IdColumn" Binding="{Binding Path=Id}" Header="Id" Visibility="Hidden" /> <DataGridTextColumn x:Name="NameColumn" Binding="{Binding Path=Name}" Header="Album Name" Width="\*" /> </DataGrid.Columns> </DataGrid> </Grid> </Window>