Git Product home page Git Product logo

winui-di-framenavigate's Introduction

WinUI Depdency Injection Frame Navigate

This is a simple sample app which demonstrates how to use the WinUI Frame.Navigate() method with Dependency Injection.

How it works

WinUI frame.Navigate method calls the IXamlType.ActivateInstance() method to create a new instance of a page. To use a SerivceProvider to create a page the IXamlType.ActivateInstance() method must be overriden. Behind the scences a source generator generates XamlTypeInfo.g.cs where some type info stuff is implemented and the App class implements the IXamlMetadataProvider interface. In the source we can see that the overriding the ActivateInstance method is directly not possible. The App class which is generated by the source generator implements the IXamlMetadataProvider interface implicitly so it is possible to 'override' the IXamlMetadataProvider interface methods with explicit implementations. Below you can see the required sections to understand how this works.
Note: the XamlTypeInfo.g.cs is located in the obj\{platform}\Debug\{targetFramework}\{runtime} folder.

XamlTypeInfo.g.cs:

namespace WinUI.DI.FrameNavigate
{
    public partial class App : global::Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
    {
        // ...
        private global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlMetaDataProvider _AppProvider { get; }

        public global::Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(global::System.Type type)
        {
            return _AppProvider.GetXamlType(type);
        }
        // ...
    }
}
namespace WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo
{
    public sealed class XamlMetaDataProvider : global::Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
    {
        // ...
        private global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlTypeInfoProvider Provider { get; }

        public global::Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(global::System.Type type)
        {
            return Provider.GetXamlType(type);
        }
    }

    internal partial class XamlTypeInfoProvider
    {
        // ...
        global::System.Type[] _typeTable = null;
        private void InitTypeTables()
        {
            // ...
            _typeTable[22] = typeof(global::WinUI.DI.FrameNavigate.Views.MainPage);
            // ...
        }

        private object Activate_22_MainPage() { return new global::WinUI.DI.FrameNavigate.Views.MainPage(); }

        private global::Microsoft.UI.Xaml.Markup.IXamlType CreateXamlType(int typeIndex)
        {
            // ...
            global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlSystemBaseType xamlType = null;
            global::System.Type type = _typeTable[typeIndex];
            switch (typeIndex)
            {
                // ...
                case 22:
                    userType = new global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlUserType(this, typeName, type, GetXamlTypeByName("Microsoft.UI.Xaml.Controls.Page"));
                    userType.Activator = Activate_22_MainPage;
                    userType.AddMemberName("ViewModel");
                    userType.SetIsLocalType();
                    xamlType = userType;
                    break;
                // ...
            }
            return xamlType;
        }
    }

    internal class XamlSystemBaseType : global::Microsoft.UI.Xaml.Markup.IXamlType
    {
        // ...
        public XamlSystemBaseType(string fullName, global::System.Type underlyingType)
        {
            // ...
        }

        public global::System.Type UnderlyingType { get; }
        // ...
    }
    
    internal delegate object Activator();
    // ...

    internal class XamlUserType : global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlSystemBaseType
        , global::Microsoft.UI.Xaml.Markup.IXamlType
    {
        public XamlUserType(global::WinUI.DI.FrameNavigate.WinUI_DI_FrameNavigate_XamlTypeInfo.XamlTypeInfoProvider provider, string fullName, global::System.Type fullType, global::Microsoft.UI.Xaml.Markup.IXamlType baseType)
            :base(fullName, fullType)
        {
            // ...
        }

        // ...
        override public object ActivateInstance()
        {
            return Activator(); 
        }
        // ...
        public Activator Activator { get; set; }
        // ...
    }
}

App.DI.cs:

namespace WinUI.DI.FrameNavigate;
file class XamlMetadataProvider : IXamlMetadataProvider
{
    // ...
    // The wrapped provider, initialized in the constructor.
    private readonly IXamlMetadataProvider _appProvider;
    // The App's ServiceProvider.
    private IServiceProvider ServiceProvider { get; }

    private void RetargetUserTypeActivator(IXamlType? xamlType)
    {
        // ...
        // The implementation is equivalent to this.
        // xamlType.Activator = () => ServiceProvider.GetService(xamlType.UnderlyingType);
    }

    public IXamlType GetXamlType(Type type)
    {
        var xamlType = _appProvider.GetXamlType(type);
        RetargetUserTypeActivator(xamlType);
        return xamlType;
    }

    public IXamlType GetXamlType(string fullName)
    {
        var xamlType = _appProvider.GetXamlType(fullName);
        RetargetUserTypeActivator(xamlType);
        return xamlType;
    }

    public XmlnsDefinition[] GetXmlnsDefinitions() => _appProvider.GetXmlnsDefinitions();
    // ...
}

partial class App : IXamlMetadataProvider
{
    // ...
    // The custom provider.
    private IXamlMetadataProvider _AppUserProvider { get; }
    IXamlType IXamlMetadataProvider.GetXamlType(Type type) => _AppUserProvider.GetXamlType(type);
    IXamlType IXamlMetadataProvider.GetXamlType(string fullName) => _AppUserProvider.GetXamlType(fullName);
    // ...
}

winui-di-framenavigate's People

Contributors

gabor-budai avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.