/// <summary>
        /// Initializes a new instance of the <see cref="NoesisWrapper" /> class.
        /// </summary>
        public NoesisWrapper(NoesisConfig config)
        {
            config.Validate();
            this.config     = config;
            this.gameWindow = config.GameWindow;

            // setup Noesis Debug callbacks
            Log.LogCallback = this.NoesisLogCallbackHandler;

            this.graphicsDevice  = config.Graphics.GraphicsDevice;
            this.providerManager = config.NoesisProviderManager;
            var provider = this.providerManager.Provider;

            GUI.SetFontProvider(provider.FontProvider);
            GUI.SetTextureProvider(provider.TextureProvider);
            GUI.SetXamlProvider(provider.XamlProvider);

            // setup theme
            if (config.ThemeXamlFilePath != null)
            {
                var themeResourceDictionary = (ResourceDictionary)GUI.LoadXaml(config.ThemeXamlFilePath);
                if (themeResourceDictionary == null)
                {
                    throw new Exception(
                              $"Theme is not found or was not able to load by NoesisGUI: {config.ThemeXamlFilePath}");
                }

                GUI.SetApplicationResources(themeResourceDictionary);
                this.Theme = themeResourceDictionary;
            }

            // create and prepare view
            var controlTreeRoot = (FrameworkElement)GUI.LoadXaml(config.RootXamlFilePath);

            this.ControlTreeRoot = controlTreeRoot
                                   ?? throw new Exception(
                                             $"UI file \"{config.RootXamlFilePath}\" is not found - cannot initialize UI");

            this.view = new NoesisViewWrapper(
                controlTreeRoot,
                this.graphicsDevice,
                this.config.CurrentTotalGameTime);
            this.RefreshSize();

            this.inputManager = this.view.CreateInputManager(config);

            // subscribe to MonoGame events
            this.EventsSubscribe();
        }
        private void DestroyRoot()
        {
            if (this.view == null)
            {
                // already destroyed
                return;
            }

            this.EventsUnsubscribe();

            this.view.Shutdown();
            this.view = null;
            var viewWeakRef = new WeakReference(this.view);

            this.view            = null;
            this.inputManager    = null;
            this.ControlTreeRoot = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();

            // ensure the view is GC'ollected
            Debug.Assert(viewWeakRef.Target == null);
        }