Page 1 of 1

Name registration error when setting ContentTemplate by code

Posted: 04 Apr 2022, 10:53
by satorp
I'm trying to switch the ContentTemplate of a ContentControl (e.g. Window or UserControl) in runtime. For example, I have a UserControl defined in XAML such as:
<UserControl x:Class="NameScopeIssue.MyControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:NameScopeIssue"
             mc:Ignorable="d">
    <Grid>
        <TextBlock x:Name="AAA" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center">AAA</TextBlock>
    </Grid>
</UserControl>
and then in my Window I use the following code to switch the Window's ContentTemplate:
            Symbol controlId("NameScopeIssue.MyControl");
            auto content = Noesis::DynamicPtrCast<ContentControl>(Noesis::Factory::CreateComponent(controlId));
            if (content)
            {
                auto contentTemplate = Noesis::MakePtr<DataTemplate>();
                contentTemplate->SetVisualTree(content.GetPtr());
                SetContentTemplate(contentTemplate);
            }
The code seems to work but Noesis reports the following error:
Cannot register duplicate name 'AAA' in this namescope.
I'm not sure if the error can be safely ignored. I tried similar code in WPF and there's no error. It seems that Noesis tries to register the name twice during template application:
  • When the template's content is cloned and added as child to TemplatedParent
  • When the template's content has a Content property, and the property is copied to the cloned element
I've found a workaround against the error by clearing the template's Content property before setting it.
                content->SetContent(Ptr<BaseComponent>()); // Avoid name registration error
                auto contentTemplate = Noesis::MakePtr<DataTemplate>();
                contentTemplate->SetVisualTree(content.GetPtr());
                SetContentTemplate(contentTemplate);
Is the workaround safe, or is there a better way to achieve this?

Re: Name registration error when setting ContentTemplate by code

Posted: 04 Apr 2022, 13:36
by sfernandez
This is happening because you are creating an instance of the UserControl (which loads all the content) and adding that to the template. Your solution of clearing the content is fine, but it would be better if you define the template using a xaml string to avoid the control instantiation:
const char* xaml = R"(
    <DataTemplate
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="namespace:NameScopeIssue">
        <local:MyControl/>
    </DataTemplate>)";

Ptr<DataTemplate> contentTemplate = StaticPtrCast<DataTemplate>(GUI::ParseXaml(xaml));

Re: Name registration error when setting ContentTemplate by code

Posted: 05 Apr 2022, 05:23
by satorp
@sfernandez Yes that approach solves the issue and is applicable to our case. Thank you.

Re: Name registration error when setting ContentTemplate by code

Posted: 05 Apr 2022, 09:40
by sfernandez
Good, thanks for the update, marking this as solved.