using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Radzen
{
///
/// Class DialogService. Contains various methods with options to open and close dialogs.
/// Should be added as scoped service in the application services and RadzenDialog should be added in application main layout.
///
///
///
/// @inject DialogService DialogService
/// <RadzenButton Text="Show dialog with inline Blazor content" Click=@ShowInlineDialog />
/// @code {
/// async Task ShowInlineDialog()
/// {
/// var result = await DialogService.OpenAsync("Simple Dialog", ds =>
/// @<div>
/// <p Style="margin-bottom: 1rem">Confirm?</p>
/// <div class="row">
/// <div class="col-md-12">
/// <RadzenButton Text="Ok" Click="() => ds.Close(true)" Style="margin-bottom: 10px; width: 150px" />
/// <RadzenButton Text="Cancel" Click="() => ds.Close(false)" ButtonStyle="ButtonStyle.Base" Style="margin-bottom: 10px; width: 150px"/>
/// <RadzenButton Text="Refresh" Click="(() => { orderID = 10249; ds.Refresh(); })" ButtonStyle="ButtonStyle.Info" Style="margin-bottom: 10px; width: 150px"/>
/// Order ID: @orderID
/// </div>
/// </div>
/// </div>);
/// Console.WriteLine($"Dialog result: {result}");
/// }
/// }
///
///
public class DialogService : IDisposable
{
private DotNetObjectReference? reference;
internal DotNetObjectReference? Reference
{
get
{
if (reference == null)
{
reference = DotNetObjectReference.Create(this);
}
return reference;
}
}
///
/// Gets or sets the URI helper.
///
/// The URI helper.
NavigationManager? UriHelper { get; set; }
IJSRuntime? JSRuntime { get; set; }
///
/// Initializes a new instance of the class.
///
/// The URI helper.
/// IJSRuntime instance.
public DialogService(NavigationManager? uriHelper, IJSRuntime? jsRuntime)
{
UriHelper = uriHelper;
JSRuntime = jsRuntime;
if (UriHelper != null)
{
UriHelper.LocationChanged += UriHelper_OnLocationChanged;
}
}
private void UriHelper_OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
{
while (dialogs.Count > 0)
{
Close();
}
if (sideDialogResultTask?.Task.IsCompleted == false)
{
CloseSide();
}
}
///
/// Raises the Close event.
///
public event Action? OnClose;
///
/// Occurs when [on refresh].
///
public event Action? OnRefresh;
///
/// Occurs when a new dialog is open.
///
public event Action, DialogOptions>? OnOpen;
///
/// Raises the Close event for the side dialog
///
public event Action? OnSideClose;
///
/// Raises the Open event for the side dialog
///
public event Action, SideDialogOptions>? OnSideOpen;
///
/// Opens a dialog with the specified arguments.
///
/// The type of the Blazor component which will be displayed in a dialog.
/// The text displayed in the title bar of the dialog.
/// The dialog parameters.
/// The dialog options.
public virtual void Open(string title, Dictionary? parameters = null, DialogOptions? options = null) where T : ComponentBase
{
OpenDialog(title, parameters, options);
}
///
/// Opens a dialog with the specified arguments.
///
/// The text displayed in the title bar of the dialog.
/// The type of the component to be displayed in the dialog. Must inherit from .
/// The dialog parameters.
/// The dialog options.
public virtual void Open(string title, Type componentType, Dictionary? parameters = null, DialogOptions? options = null)
{
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
{
throw new ArgumentException("The component type must be a subclass of ComponentBase.", nameof(componentType));
}
var method = GetType().GetMethod(nameof(OpenDialog), BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new InvalidOperationException("OpenDialog method not found.");
}
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters!, options! });
}
///
/// Invokes .
///
public void Refresh()
{
OnRefresh?.Invoke();
}
///
/// The tasks
///
protected List> tasks = new List>();
private TaskCompletionSource? sideDialogResultTask;
///
/// Opens a dialog with the specified arguments.
///
/// The type of the Blazor component which will be displayed in a dialog.
/// The text displayed in the title bar of the dialog.
/// The dialog parameters. Passed as property values of .
/// The dialog options.
/// The value passed as argument to .
public virtual Task OpenAsync(string title, Dictionary? parameters = null, DialogOptions? options = null) where T : ComponentBase
{
var task = new TaskCompletionSource();
tasks.Add(task);
OpenDialog(title, parameters, options);
return task.Task;
}
///
/// Opens a dialog with the specified arguments dynamically.
///
/// The text displayed in the title bar of the dialog.
/// The type of the Blazor component to be displayed in a dialog. Must inherit from .
/// The dialog parameters, passed as property values of the specified component.
/// The dialog options.
/// A task that represents the result passed as an argument to .
/// Thrown if does not inherit from .
public virtual Task OpenAsync(string title, Type componentType, Dictionary? parameters = null, DialogOptions? options = null)
{
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
{
throw new ArgumentException("The component type must be a subclass of ComponentBase.", nameof(componentType));
}
var task = new TaskCompletionSource();
tasks.Add(task);
var method = GetType().GetMethod(nameof(OpenDialog), BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new InvalidOperationException("OpenDialog method not found.");
}
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters!, options! });
return task.Task;
}
///
/// Opens a side dialog with the specified arguments
///
/// The type of Blazor component which will be displayed in the side dialog.
/// The text displayed in the title bar of the side dialog.
/// The dialog parameters. Passed as property values of
/// The side dialog options.
/// A task that completes when the dialog is closed or a new one opened
public Task OpenSideAsync(string title, Dictionary? parameters = null, SideDialogOptions? options = null)
where T : ComponentBase
{
CloseSide();
sideDialogResultTask = new TaskCompletionSource();
if (options == null)
{
options = new SideDialogOptions();
}
options.Title = title;
OnSideOpen?.Invoke(typeof(T), parameters ?? new Dictionary(), options);
return sideDialogResultTask.Task;
}
///
/// Opens a side dialog with the specified arguments dynamically.
///
/// The text displayed in the title bar of the side dialog.
/// The type of the Blazor component to be displayed in the side dialog. Must inherit from .
/// The dialog parameters, passed as property values of the specified component.
/// The side dialog options.
/// A task that represents the result passed as an argument to .
/// Thrown if does not inherit from .
public Task OpenSideAsync(string title, Type componentType, Dictionary? parameters = null, SideDialogOptions? options = null)
{
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
{
throw new ArgumentException("The component type must be a subclass of ComponentBase.", nameof(componentType));
}
CloseSide();
sideDialogResultTask = new TaskCompletionSource();
if (options == null)
{
options = new SideDialogOptions();
}
options.Title = title;
OnSideOpen?.Invoke(componentType, parameters ?? new Dictionary(), options);
return sideDialogResultTask.Task;
}
///
/// Opens a side dialog with the specified arguments
///
/// The type of Blazor component which will be displayed in the side dialog.
/// The text displayed in the title bar of the side dialog.
/// The dialog parameters. Passed as property values of
/// The side dialog options.
public void OpenSide(string title, Dictionary? parameters = null, SideDialogOptions? options = null)
where T : ComponentBase
{
CloseSide();
if (options == null)
{
options = new SideDialogOptions();
}
options.Title = title;
OnSideOpen?.Invoke(typeof(T), parameters ?? new Dictionary(), options);
}
///
/// Opens a side dialog with the specified arguments dynamically.
///
/// The text displayed in the title bar of the side dialog.
/// The type of the Blazor component to be displayed in the side dialog. Must inherit from .
/// The dialog parameters, passed as property values of the specified component.
/// The side dialog options.
/// Thrown if does not inherit from .
public void OpenSide(string title, Type componentType, Dictionary? parameters = null, SideDialogOptions? options = null)
{
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
{
throw new ArgumentException("The component type must be a subclass of ComponentBase.", nameof(componentType));
}
CloseSide();
if (options == null)
{
options = new SideDialogOptions();
}
options.Title = title;
OnSideOpen?.Invoke(componentType, parameters ?? new Dictionary(), options);
}
///
/// Closes the side dialog
///
/// The result of the Dialog
public virtual void CloseSide(dynamic? result = null)
{
if (sideDialogResultTask?.Task.IsCompleted == false)
{
sideDialogResultTask.TrySetResult(result);
}
OnSideClose?.Invoke(result);
}
private TaskCompletionSource? sideDialogCloseTask;
internal void OnSideCloseComplete()
{
sideDialogCloseTask?.TrySetResult();
sideDialogCloseTask = null;
}
///
/// Closes the side dialog and waits for the closing animation to finish.
///
/// The result of the Dialog
public async Task CloseSideAsync(dynamic? result = null)
{
sideDialogCloseTask = new TaskCompletionSource();
CloseSide(result);
await sideDialogCloseTask.Task;
}
///
/// Opens a dialog with the specified content.
///
/// The text displayed in the title bar of the dialog.
/// The content displayed in the dialog.
/// The dialog options.
/// The cancellation token.
/// The value passed as argument to .
public virtual Task OpenAsync(string title, RenderFragment childContent, DialogOptions? options = null, CancellationToken? cancellationToken = null)
{
var task = new TaskCompletionSource();
// register the cancellation token
if (cancellationToken.HasValue)
cancellationToken.Value.Register(() => task.TrySetCanceled());
tasks.Add(task);
options ??= new DialogOptions();
options.ChildContent = childContent;
OpenDialog