Open PhilippCh opened 5 years ago
I have been asking for the same thing.
There should be a factory type that instantiates these templates and that can be extended. For instance, to inject a IServiceProvider through the constructor and get the page instance from there.
I also think that Microsoft.Extension.DependencyInjection should be used in all of Xamarin.Forms (in one place) instead of the confusing integration points today.
In that way you could use whatever IoC container you want too.
I'm curious, has someone already investigated how to implement this without breaking the current integration points?
@robertsundstrom : Maybe this one is what you are looking for.
I would also like to see Shell supporting the feature of being able to be instantiated using dependency injection. As of now, I have to have my content pages with parameterless constructors, and having a static reference to my IServiceProvider
to resolve the page's dependencies. It works but doesn't follow the DI pattern used in the rest of classes in my Xamarin.Forms project.
Hopefully Shell allows us to instantiate it using DI soon.
We have some discussions around this going on
I also think that Microsoft.Extension.DependencyInjection should be used in all of Xamarin.Forms (in one place) instead of the confusing integration points today.
would be my preference.
If we add our own DI then that's just going to scope creep into a lot of work maintaining our own IoC framework
The current DependencyResolver is fairly specific in its intent
So the question becomes if there's enough value add to make Microsoft.Extension.DependencyInjection default? or do we just build a separate nuget you can use that to plugin with?
I sometimes prefer to pass models and services into the constructors of Pages.
I prefer that to the ViewModelLocator pattern since you can wire up instances on the fly from code without depending on a single class that also grows in size.
Second thought, it is kind of weird aesthetically to instantiate a XAML element by injecting an object into a constructor.
Property injection seems OK.
DI seems to suit Blazor better.
Firstly, you guys are far ahead of me here as I'm quite new to Xamarin. After working with master view for some days I've just discovered Xamarin Shell today and was doing a quick app to play with the navigation.
You've mentioned there is already a "way" to achieve a view model first navigation with shell (and maybe use a DI container to instantiate the view models) and you've mentioned ElementTemplate
for that. Would you mind sharing a link or sample where this is being used?
I don't mind if I have to manually use the DI container to instantiate view models prior to binding them at some "central point" (AppShell.xaml.cs
?), but I'm keen on seeing what's the best approach as per today. Thanks
If you create ShellItems with code, and the class comes from IoC you can add you service provider and call: ` new ShellContent { ContentTemplate = new DataTemplate(()=> _provider.GetService(menu.Type)) }
`
@payoff And when I think about it, you could create a markup extension that wraps this functionality in a generic way.
<ShellContent ContentTemplate="{local:DIDataTemplate Type={x:Type MyPage}}" />
It would require you to either assign a static IServiceProvider to the Markup Extension, or have a standard Service Locator.
public class App : Application
{
public App()
{
DIDataTemplate.AppServiceProvider = // your service provider;
}
}
public class DIDataTemplate : IMarkupExtension<DataTemplate>
{
public static IServiceProvider AppServiceProvider { set; get; }
public Type Type { set; get; }
public DataTemplate ProvideValue(IServiceProvider serviceProvider)
{
return new DataTemplate(()=> AppServiceProvider.GetService(Type))
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return (this as IMarkupExtension<DataTemplate>).ProvideValue(serviceProvider);
}
}
This will find its way into MAUI, but won't be showing up in Xamarin.Forms. See https://github.com/xamarin/Xamarin.Forms/issues/10804#issuecomment-981494921
Summary
Please add the capability to use an IoC container of our choice when creating new pages via (shell) XAML files.
API Changes
Instead of using
Activator.CreateInstance()
in ElementTemplate, create a way for us to provide our own callback for creation of new instances.Note: I know this currently already works with Xamarin.Forms by simply creating the page types from the IoC container for example within App for the first page, but Shell doesn't provide a coherent way to integrate an IoC container as of now.
Intended Use Case
This would allow us to use for example an IoC framework of our choice.