• The importance of the position of Window.Resources element in WPF XAML markup

    by  • October 5, 2011 • Uncategorized • 0 Comments

    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 dictionary
                CollectionViewSource src = ((CollectionViewSource)Resources["AlbumsSource"]);
                
                using (var ent = new MusicTrackerContainer()) {
                    src.Source = ent.Albums;
                }
            }
    

    Where 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.’.

    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:

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

    About

    .NET developer at thetrainline.com, previously web developer at MRM Meteorite. Awarded a PhD in misbehaviour detection in wireless ad-hoc networks.A keen C# ASP.net developer bridging the gap with APIs and JavaScript frameworks, one web app at a time.

    http://www.paulkiddie.com

    Leave a Reply

    Your email address will not be published. Required fields are marked *