satorp
Topic Author
Posts: 20
Joined: 12 Mar 2018, 05:48

Name registration error when setting ContentTemplate by code

04 Apr 2022, 10:53

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?
Attachments
NameScopeIssue.zip
(6.21 KiB) Downloaded 277 times
 
User avatar
sfernandez
Site Admin
Posts: 3364
Joined: 22 Dec 2011, 19:20

Re: Name registration error when setting ContentTemplate by code

04 Apr 2022, 13:36

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));
 
satorp
Topic Author
Posts: 20
Joined: 12 Mar 2018, 05:48

Re: Name registration error when setting ContentTemplate by code

05 Apr 2022, 05:23

@sfernandez Yes that approach solves the issue and is applicable to our case. Thank you.
 
User avatar
sfernandez
Site Admin
Posts: 3364
Joined: 22 Dec 2011, 19:20

Re: Name registration error when setting ContentTemplate by code

05 Apr 2022, 09:40

Good, thanks for the update, marking this as solved.

Who is online

Users browsing this forum: No registered users and 9 guests