Page 1 of 1

Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 14 Aug 2020, 15:19
by blafollette
I've got a big collection of flags that are stored in a <ResourceDictionary x:Name="myName"> in xaml. I wrote an IValueConverter that takes an input string from an item property in a collection and returns the svg resource. The code behind for the xaml exposes a ResouceDictionary property that I use in the IValueConverter to reference the dictionary and return values by key.

This is all working great in WPF, but in Unity when I call FindName("myName") to manually assign the ResourceDictionary to the accessor property, it throws an exception "System.InvalidOperationException: Native type is not registered". What am I doing wrong? Am I missing something?

Or, more generally, is there a better approach to displaying svg flags or icons or whatever than storing them as keyed resources in xaml?

Help! :)

for reference, here's some of my code:
The wrapper xaml
<UserControl x:Class="MyNamespace.FlagsWrapper"
             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:MyNamespace"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
		<ResourceDictionary x:Name="FlagsResource"> Source="Styles/FlagsCollection.xaml"/>
    </UserControl.Resources>
</UserControl>
The code-behind
public partial class FlagsWrapper : UserControl
    {
        public ResourceDictionary FlagsDictionary { get; set; }

        public FlagsWrapper()
        {
            InitializeComponent();

#if !NOESIS
            FlagsDictionary = FlagsResource;
#endif
        }

#if NOESIS
        private void InitializeComponent()
        {
            Noesis.GUI.LoadComponent(this, "Assets/WPF/FlagsWrapper.xaml");
            FlagsDictionary = FindName("FlagsResource") as ResourceDictionary;
        }
#endif
    }
And finally my accessor in the IValueConverter:
        private ResourceDictionary m_flags;
        public ResourceDictionary Flags
        {
            get
            {
                if (m_flags == null)
                    m_flags = new FlagsWrapper().FlagsDictionary;

                return m_flags;
            }
        }

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 14 Aug 2020, 20:27
by sfernandez
It seems there is a bug when defining a ResourceDictionary with x:Name inside <Resources> node, could you please report it in our bugtracker?

Anyway, assigning the dictionary to the converter like this looks too complex for me, shouldn't be enough to expose a Flags property in the converter and set it in the xaml directly:
public class FlagConverter : Noesis.IValueConverter
{
  public ResourceDictionary Flags { get; set; }

  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { ... }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { ... }
}
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:Testing">
  <Grid.Resources>
    <local:FlagConverter x:Key="flagConverter">
      <local:FlagConverter.Flags>
        <ResourceDictionary Source="FlagsCollection.xaml"/>
      </local:FlagConverter.Flags>
    </local:FlagConverter>
  </Grid.Resources>
  ...
</Grid>
Or, more generally, is there a better approach to displaying svg flags or icons or whatever than storing them as keyed resources in xaml?
Using keyed resources/templates to store svg icons is fine, this way you can reuse them and share other resources like brushes to reduce memory usage.

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 15 Aug 2020, 14:39
by blafollette
Thanks so much! I will certainly go ahead and make a report.

As for the solution you suggest, I actually did exactly this as my initial approach! However, it broke the VS designer view, and part of my whole reason for taking this approach was to allow for design-time display of these SVGs. :) Apparently, the Design viewer uses a different object to instantiate the ResourceDictionary than the runtime, and it didn't want to play nice. And having the designer view being broken and refusing to render was not an option.

My next approach was to simply create a code-behind which derived from ResourceDictionary for the xaml file where I define the <ResourceDictionary> for the SVGs as the top-level element. I then simply instanced a new version of this file in my converter's accessor for the dictionary on demand. This actually worked, too! (in both WPF and Unity/Noesis) However, defining the code behind class for the <ResourceDictionary> was spamming the Unity console with errors complaining that I couldn't define a ResourceDictionary inside of a ResourceDictionary (?), I would have to recreate the scenario to get the exact error message, but I decided I wasn't satisfied with this approach since it broke the pattern used with the other style xamls that I have anyway.

So hence, finally, my third approach, which got us here! :D

Thanks again!

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 17 Aug 2020, 13:21
by blafollette
For any curious, the workaround that has everything working was to implement my Resources node in my Flags Wrapper xaml as follows:
    <UserControl.Resources>
        <ResourceDictionary x:Name="FlagsResource">
            <ResourceDictionary.MergedDictionaries >
                <ResourceDictionary Source="Styles/FlagsCollection.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <local:ISOtoFlagConverter x:Key="flagConverter" x:Name="FlagConverter">
                <local:ISOtoFlagConverter.Flags>
                    <ResourceDictionary Source="Styles/FlagsCollection.xaml"/>
                </local:ISOtoFlagConverter.Flags>
            </local:ISOtoFlagConverter>
        </ResourceDictionary>
    </UserControl.Resources>
And then to use compilation directives in the code behind as follows:
    public partial class FlagsWrapper : UserControl
    {
        public ResourceDictionary FlagsDictionary { get; set; }

        public FlagsWrapper()
        {
            InitializeComponent();

#if !NOESIS
            FlagsDictionary = FlagsResource;
#endif
        }

#if NOESIS
        private void InitializeComponent()
        {
            Noesis.GUI.LoadComponent(this, "Assets/FlagsWrapper.xaml");
            var converter = FindName("FlagConverter") as FlagConverter;
            FlagsDictionary = converter.Flags;
        }
#endif
    }

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 20 Aug 2020, 10:59
by sfernandez
As for the solution you suggest, I actually did exactly this as my initial approach! However, it broke the VS designer view, and part of my whole reason for taking this approach was to allow for design-time display of these SVGs. :) Apparently, the Design viewer uses a different object to instantiate the ResourceDictionary than the runtime, and it didn't want to play nice. And having the designer view being broken and refusing to render was not an option.
The solution I proposed works fine with Blend designer, please find attached a sample project for you to test. I guess you implemented a slightly different approach.

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 20 Aug 2020, 11:04
by blafollette
It's entirely possible the error was all my own doing! :) Thanks for the sample, I'll give it a test as soon as I have the opportunity!

Thanks very much, again, for all your help!

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 20 Aug 2020, 15:30
by blafollette
Yup, this totally works just as you said! I don't know what I got wrong before, but I'm no longer even able to reproduce the original design view error I got. So, no idea where I went wrong before! :)

Thanks again!

Re: Native type is not registered error when calling FindName("myName") as ResourceDictionary

Posted: 24 Aug 2020, 13:32
by jsantos
Great! Marking as solved