dependency-injectionmauistaticresource

How can I reference Colors.xaml in MauiProgram.cs?


My problem is that I'm referencing a static resource, primary (as a color) in my MainPage, but when I have MainPage in the constructor of App() for Dependency Injection, primary isn't defined yet because its reference is loaded from App.xaml.

public partial class App : Application
{
    //MainPage gets loaded first with a reference to
    //StaticResource Primary which doesn't exist yet.
    //An exception is thrown in mp.InitializeComponent()
    //complaining about StaticResource Primary not existing
    public App(MainPage mp, MainPageViewModel vm)
    {
        //StaticResource Primary is defined in here
        InitializeComponent();

        MainPage = mp;
        MainPage.BindingContext= vm;
    }
}

I can work around this by doing the following:

Adding Colors (and Styles) to the ResourceDictionary of MainPage:

<ContentPage.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/Styles/Colors.xaml" />
            <ResourceDictionary Source="Resources/Styles/Styles.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</ContentPage.Resources>

But then I also have to add a ResourceDictionary in Styles.xaml referencing Colors.xaml:

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Colors.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

This approach is fine for a small app, but I have many view pages utilizing Colors.xaml in the app I'm developing. Is there any way I can globally reference Colors.xaml and Styles.xaml in MauiProgram.cs? (So they're registered before DI takes place with MainPage)


Solution

  • You don't need to reference colors. What you actually ask is: "How to resolve services with dependency injection".

    You can add to any class IServiceProvider, and "ask" for a service to be provided to you. When you "ask" for your View, it will cascade (or to use your term: dominos down the line) and call the required constructors for ViewModel. And if your ViewModel uses something like ISettings, It will call the constructor of your MySettings class that implements the interface and so on.

    The whole idea of using DI is to let it do this work for you.

    You should not pass pages, in the constructor of you Application class. Why? Because when you construct it, LoadFromXaml is not called yet. But nothing is stopping you from having IServiceProvider in your constructor. And request services after Initialization is done.

    This is good theory: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-7.0

    This is good example: https://stackoverflow.com/a/32461714/6643940