I need to show material alert dialog. I have created implementation and want to use it in any place of my code.
I know that in MAUI we can register class: builder.Services.AddSingleton(typeof(IDialogService), typeof(DialogService));
How to use this instead of injecting in constructor? Because I prefer viewModels with empty constructors.
For example like in Xamarin Forms: DependencyService.Get<IDialogService>();
In blazor we can write something like @inject IDialogService DialogService
I remember in Xamarin Forms creating singleton class is popular solution:
public class MenuService : IMenuService
{
private static Lazy<IMenuService> _instance = new Lazy<IMenuService>(() => new MenuService(), System.Threading.LazyThreadSafetyMode.PublicationOnly);
public static IMenuService Instance => _instance.Value;
public Task<string> ShowMenu(View view, string[] items) =>
DependencyService.Get<IMenuService>().ShowMenu(view, items);
}
I want to create something similar to this approach for my maui service. How to do this properly?
My implementation:
public interface IDialogService
{
Task<string> ShowDialog(string title, string message, string accept, string cancel, string neutral);
Task<bool> ShowDialog(string title, string message, string accept, string cancel);
}
public partial class DialogService : IDialogService
{
public partial Task<string> ShowDialog(string title, string message, string accept, string cancel, string neutral);
public partial Task<bool> ShowDialog(string title, string message, string accept, string cancel);
}
Android implementation:
public partial class DialogService : IDialogService
{
static Context context;
internal static Context Context
{
get
{
var page = Application.Current.MainPage;
var renderer = page.GetRenderer();
if (renderer?.View.Context != null)
context = renderer.View.Context;
return renderer?.View.Context ?? context ?? throw new NullReferenceException($"{nameof(Context)} cannot be null");
}
}
private ISpanned FromHtml(string message)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
return Html.FromHtml(message, FromHtmlOptions.ModeLegacy);
return Html.FromHtml(message);
}
public partial Task<string> ShowDialog(string title, string message, string accept, string cancel, string neutral)
{
TaskCompletionSource<string> taskCompletionSource = new TaskCompletionSource<string>();
MaterialAlertDialogBuilder alertBuilder = new MaterialAlertDialogBuilder(Context);
alertBuilder
.SetTitle(title)
.SetMessage(FromHtml(message))
.SetPositiveButton(accept, (sender, args) => taskCompletionSource.SetResult(accept));
if (cancel != null)
alertBuilder.SetNegativeButton(cancel, (sender, args) => taskCompletionSource.SetResult(cancel));
if (neutral != null)
alertBuilder.SetNeutralButton(neutral, (sender, args) => taskCompletionSource.SetResult(neutral));
AndroidX.AppCompat.App.AlertDialog dialog = alertBuilder.Create();
dialog.CancelEvent += (object sender, EventArgs e) => taskCompletionSource?.SetResult(null);
dialog.Show();
return taskCompletionSource.Task;
}
public partial Task<bool> ShowDialog(string title, string message, string accept, string cancel)
{
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
MaterialAlertDialogBuilder alertBuilder = new MaterialAlertDialogBuilder(Context);
alertBuilder
.SetTitle(title)
.SetMessage(FromHtml(message))
.SetPositiveButton(accept, (sender, args) => taskCompletionSource.SetResult(true))
.SetNegativeButton(cancel, (sender, args) => taskCompletionSource.SetResult(false));
AndroidX.AppCompat.App.AlertDialog dialog = alertBuilder.Create();
dialog.CancelEvent += (object sender, EventArgs e) => taskCompletionSource?.SetResult(false);
dialog.Show();
return taskCompletionSource.Task;
}
}