0

I've been following the Microsoft documentation to try simplifying the App.xaml and App.xaml.cs files from the standard VisualStudio Blank WinUI 3 template into a single App.cs file.

So far, I've got a version that compiles:

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace MyApp;

public class App : Application
{
    private Window _mainWindow;

    public App() {}

    protected override void OnLaunched( LaunchActivatedEventArgs args )
    {
        Resources = new ResourceDictionary();
        Resources.MergedDictionaries.Add( new XamlControlsResources() );

        _mainWindow = new MainWindow();
        _mainWindow.Activate();
    }

    public static void Main( string[] args )
    {
        App.Start(
            ( ApplicationInitializationCallbackParams callback ) =>
            {
                new App();
            }
        );
    }
}

But it doesn't end up actually launching the UI because the call new XamlControlsResources() throws a System.Runtime.InteropServices.COMException with the message Unspecified Error.

Is there any way to bootstrap a WinUI3 / Windows App SDK / .NET app in C# code without the Xaml?

Update

As you can see, I've accepted Jeaninez - MSFT's answer (below).

Here is what the final working App.cs file, which uses the type Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsXamlMetaDataProvider to satisfy the interface Microsoft.UI.Xaml.Markup.IXamlMetadataProvider, as in the C++ project on GitHub that Jean recommended.

(Note that the call Resources.MergedDictionaries.Add( new XamlControlsResources() ); must occur within the OnLaunched override. If you call it in the App constructor, it throws the System.Runtime.InteropServices.COMException that I referred to above.)

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;
using Microsoft.UI.Xaml.XamlTypeInfo;
using System;

namespace MyApp;

public class App : Application, IXamlMetadataProvider
{
    private Window _mainWindow;
    private XamlControlsXamlMetaDataProvider provider;

    public App() { }

    [ STAThread ]
    public static void Main( string[] args )
    {
        Application.Start(
            ( ApplicationInitializationCallbackParams callback ) =>
            {
                new App();
            }
        );
    }

    public IXamlType GetXamlType( string fullName )
    {
        return provider.GetXamlType( fullName );
    }

    public IXamlType GetXamlType( Type type )
    {
        return provider.GetXamlType( type );
    }

    public XmlnsDefinition[] GetXmlnsDefinitions()
    {
        return provider.GetXmlnsDefinitions();
    }

    protected override void OnLaunched( LaunchActivatedEventArgs args )
    {
        XamlControlsXamlMetaDataProvider.Initialize();
        provider = new();

        Resources.MergedDictionaries.Add( new XamlControlsResources() );

        _mainWindow = new MainWindow();
        _mainWindow.Activate();
    }
}
Leo Orientis
  • 841
  • 11
  • 19

1 Answers1

2

As far as I'm concerned, what you need to do is implementing a IXamlMetadataProvider interface. This interface implements XAML type resolution and provides the mapping between types used in XAML markup and the corresponding classes implemented in an application or component.

For more details, I suggest you could refer to the c++ sample: WinUI 3 in C++ Without XAML

Jeaninez - MSFT
  • 3,210
  • 1
  • 5
  • 20
  • Thanks very much! In addition to adding using `Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsXamlMetaDataProvider` to satisfy the `Microsoft.UI.Xaml.Markup.IXamlMetadataProvider` interface, I also had to move the call to `Resources.MergedDictionaries.Add( new XamlControlsResources() )` to the `OnLaunched` method. – Leo Orientis Jun 12 '23 at 20:36