Happy new year to everyone!
My question concerns how to use DI in a Xamarin.Forms View to resolve a ViewModel where the ViewModel needs a dynamic (different every time) constructor parameter which parameter needs to be constructed inside the View. If it is feasible, I would like to use ASP NET Core DI. I have read James Montemagno's post about DI, but I dont think it contains the answer to my question.
Here is my code in its current, non-DI form:
We are inside the MovieDetailPage() constructor and the Page's constructor creates its own ViewModel and assigns it to its binding context like this:
public MovieDetailPage(MovieDetailModel movie) { ViewModel = new MovieDetailPageViewModel( movie, ((App)Application.Current).Settings, ((App)Application.Current).TmdbApiService, ((App)Application.Current).UsersMovieListsService2, ((App)Application.Current).MovieDetailModelConfigurator, ((App)Application.Current).PersonDetailModelConfigurator, ((App)Application.Current).VideoService, ((App)Application.Current).WeblinkComposer, **new PageService(this)** ); InitializeComponent(); }
The page extracts the dependencies from the Application by accessing the properties in ((App)Application.Current).. These dependencies have a lifetime equal to the application and do not change. My understanding is, that we could easily resolve them via DI if we register them with Singleton lifetime.
My problem is the object which the Page constructs via new PageService(this) . PageService basically provides means for the ViewModel to access some Xamarin.Forms navigation and DisplayAlert() functions by exposing some of the API of Navigation and Page through an IPageService interface.
For this the PageService object needs to be constructed dynamically with the current pages reference.
What options do I have to use Dependency Injection for resolving the ViewModel from the View's constructor in a way so that I can provide a valid PageService object. For better understanding I have copied some code from IPageService-PageService below.
====================================================================
public interface IPageService { .. Task DisplayAlert(string title, string message, string cancel); ... Task OpenWeblink(string url); } public class PageService : IPageService { private readonly Page _currentPage; public PageService(Page current) => _currentPage = current; ... public async Task DisplayAlert(string title, string message, string cancel) => await _currentPage.DisplayAlert(title, message, cancel); ... public async Task OpenWeblink(string url) { try { await Browser.OpenAsync(url, BrowserLaunchMode.SystemPreferred); } catch (Exception ex) { await _currentPage.DisplayAlert("Error", $"Could not open weblink: {ex.Message}", "Ok"); } } }