1

Let's say I have a simple DataTemplate declaration; it doesn't even need content:

<DataTemplate x:Key="myListBoxItemTemplate" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />

..which is generated from the following C# code:

    private string GenerateDataTemplateXaml()
    {
        const string xamlNamespaceString = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        const string xamlXNamespaceString = "http://schemas.microsoft.com/winfx/2006/xaml";
        XNamespace defaultNamespace = xamlNamespaceString;
        XNamespace x = xamlXNamespaceString;

        XElement dataTemplate =
            new XElement(defaultNamespace + "DataTemplate",
                new XAttribute(x + "Key", "myListBoxItemTemplate"),
                new XAttribute(XNamespace.Xmlns + "x", xamlXNamespaceString),
                new XAttribute("xmlns", xamlNamespaceString));                   

        return dataTemplate.ToString();
    }

I want to load this into my MainWindow's Resources using XamlReader.Parse on the generated XAML string.

    public MainWindow()
    {
        InitializeComponent();

        string dataTemplateText = this.GenerateDataTemplateXaml();
        DataTemplate dataTemplate = (DataTemplate)XamlReader.Parse(dataTemplateText);
    }

This runs without exception, but the resulting DataTemplate doesn't have its DataTemplateKey property set (it's null). I would expect this to have a value of "myListBoxItemTemplate". So, if I want to add this template to the MainWindow's resources, I need to refer to the key again explicitly (which seems redundant):

this.Resources.Add("myListBoxItemTemplate", dataTemplate);

Why is dataTemplate.DataTemplateKey null after loading valid XAML which defines this key?

(I've got bigger issues I'm encountering but this may clue me in as to why those are happening as well.)

vargonian
  • 3,064
  • 3
  • 27
  • 36

1 Answers1

1

Setting x:Key does not set the DataTemplate's DataTemplateKey property.

It is the other way round. See the Remarks:

If you do not set the x:Key Directive on a DataTemplate that is in a ResourceDictionary, the DataTemplateKey is used as the key.

Clemens
  • 123,504
  • 12
  • 155
  • 268
  • Interesting, I have absolutely no idea how DataTemplateKey would ever be set on a DataTemplate then. It's not set when parsed with XamlReader.Parse. it can't be set by consumers because it has an inaccessible setter. It's not set when calling ResourceDictionary.Add(key, template). – vargonian Mar 16 '19 at 20:21
  • A look at the [reference source](https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/DataTemplate.cs,623bc07124c7ba7a) reveals: `public object DataTemplateKey { get { return (DataType != null) ? new DataTemplateKey(DataType) : null; }}`. Which is exactly what you would expect from the documentation. `DataTemplateKey` gives you a default key that corresponds to its DataType. No DataType, no default key. – Clemens Mar 16 '19 at 20:33
  • Alright, thank you, now that I've solved that problem unfortunately I have to move onto the next, which is that subsequently loaded XAML controls can't find this DataTemplate resource even after it's been added to the Window's resource dictionary and clearly shows up in the debugger. I will make a new question for this. – vargonian Mar 16 '19 at 20:46
  • I posted the related question here, FYI: https://stackoverflow.com/questions/55231130/how-to-reference-existing-resources-from-a-xamlreader-parsexmlfragment-call Not sure if you know why that behavior exists but I thought I'd link it just in case. Thanks again. – vargonian Mar 18 '19 at 22:57