XAMLParser-created DataTemplate: Correct way to reference a StaticResource

691 Views Asked by At

I'm creating a DataTemplate in code using a XamlReader:

public DataTemplate CreateDataTemplate()
{
    string template = @"<DataTemplate >
                            <StackPanel>        
                                <ComboBox ItemsSource=""{Binding Source={StaticResource collectibleTypeFromEnum}}"" />              
                            </StackPanel>
                        </DataTemplate>";

    ParserContext context = new ParserContext();
    context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
    context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
    context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

    // This is meant to provide reference to where collectibleTypeFromEnum lives
    context.XamlTypeMapper.AddMappingProcessingInstruction("myview", "MyProgram.View", "MyProgram, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
    context.XmlnsDictionary.Add("myview", "myview");

    return XamlReader.Parse(template, context) as DataTemplate;
}

The XAMLParser successfully parses the string and returns a DataTemplate, but it then crashes at runtime ('System.Windows.Markup.XamlParseException': "Provide value on 'System.Windows.Markup.StaticResourceHolder'"). I need help providing the correct reference to that StaticResource, and I can't figure it out.

I'm trying to provide the correct namespace/reference via the ParserContext (see above), but clearly I'm doing it wrong. If I retrieve the ObjectDataProvider from the XAML and add it to the Application's global resources instead (Application.Current.Resources.Add()) everything works. But it seems to me that I should be able to directly reference the XAML resource.

The converter in question is defined in a user control (the same one the DataTemplate initially lived in, so the DT had no problem finding it):

<UserControl x:Class="MyProgram.View.CollectibleDetail"
             [...] >
    <UserControl.Resources>
    <ObjectDataProvider x:Key="collectibleTypeFromEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="model:ECollectibleType"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</UserControl.Resources>
1

There are 1 best solutions below

4
mm8 On BEST ANSWER

StaticResource doesn't support forward referencing. You could either add the resource to Application.Current.Resources in order to make it available throughout your entire application or you could use {DynamicResource}:

string template = @"<DataTemplate >
                    <StackPanel>        
                        <ComboBox ItemsSource=""{DynamicResource collectibleTypeFromEnum}"" />              
                    </StackPanel>
                </DataTemplate>";