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(title, null, options); return task.Task; } /// /// Opens a dialog with the specified content. /// /// The content 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(RenderFragment titleContent, 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; options.TitleContent = titleContent; OpenDialog(null, null, options); return task.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. public virtual void Open(string title, RenderFragment childContent, DialogOptions? options = null) { options = options ?? new DialogOptions(); options.ChildContent = childContent; OpenDialog(title, null, options); } /// /// The dialogs /// protected List dialogs = new List(); internal void OpenDialog(string? title, Dictionary? parameters, DialogOptions? options) { dialogs.Add(new object()); // Validate and set default values for the dialog options options ??= new(); parameters ??= new Dictionary(); options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : "600px"; options.Left = !String.IsNullOrEmpty(options.Left) ? options.Left : ""; options.Top = !String.IsNullOrEmpty(options.Top) ? options.Top : ""; options.Bottom = !String.IsNullOrEmpty(options.Bottom) ? options.Bottom : ""; options.Height = !String.IsNullOrEmpty(options.Height) ? options.Height : ""; options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? options.CssClass : ""; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? options.WrapperCssClass : ""; options.ContentCssClass = !String.IsNullOrEmpty(options.ContentCssClass) ? options.ContentCssClass : ""; OnOpen?.Invoke(title, typeof(T), parameters, options); } /// /// Closes the last opened dialog with optional result. /// /// The result. [JSInvokable("DialogService.Close")] public virtual void Close(dynamic? result = null) { var dialog = dialogs.LastOrDefault(); if (dialog != null) { OnClose?.Invoke(result); dialogs.Remove(dialog); } var task = tasks.LastOrDefault(); if (task != null && task.Task != null && !task.Task.IsCompleted) { tasks.Remove(task); task.SetResult(result); } } /// public void Dispose() { reference?.Dispose(); reference = null; UriHelper?.LocationChanged -= UriHelper_OnLocationChanged; } /// /// Displays a confirmation dialog. /// /// The message displayed to the user. /// The text displayed in the title bar of the dialog. /// The options. /// The cancellation token. /// true if the user clicked the OK button, false otherwise. public virtual async Task Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions? options = null, CancellationToken? cancellationToken = null) { // Validate and set default values for the dialog options options ??= new(); options.OkButtonText = !String.IsNullOrEmpty(options.OkButtonText) ? options.OkButtonText : "Ok"; options.CancelButtonText = !String.IsNullOrEmpty(options.CancelButtonText) ? options.CancelButtonText : "Cancel"; options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; // Width is set to 600px by default by OpenAsync options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-confirm {options.CssClass}" : "rz-dialog-confirm"; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; return await OpenAsync(title, ds => { RenderFragment content = b => { var i = 0; b.OpenElement(i++, "p"); b.AddAttribute(i++, "class", "rz-dialog-confirm-message"); b.AddContent(i++, message); b.CloseElement(); b.OpenElement(i++, "div"); b.AddAttribute(i++, "class", "rz-dialog-confirm-buttons"); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.OkButtonText); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(true))); b.CloseComponent(); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.CancelButtonText); b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Base); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(false))); b.CloseComponent(); b.CloseElement(); }; return content; }, options, cancellationToken); } /// /// Displays a confirmation dialog. /// /// The message displayed to the user. /// The text displayed in the title bar of the dialog. /// The options. /// The cancellation token. /// true if the user clicked the OK button, false otherwise. public virtual async Task Confirm(RenderFragment message, string title = "Confirm", ConfirmOptions? options = null, CancellationToken? cancellationToken = null) { // Validate and set default values for the dialog options options ??= new(); options.OkButtonText = !String.IsNullOrEmpty(options.OkButtonText) ? options.OkButtonText : "Ok"; options.CancelButtonText = !String.IsNullOrEmpty(options.CancelButtonText) ? options.CancelButtonText : "Cancel"; options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; // Width is set to 600px by default by OpenAsync options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-confirm {options.CssClass}" : "rz-dialog-confirm"; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; return await OpenAsync(title, ds => { RenderFragment content = b => { var i = 0; b.OpenElement(i++, "p"); b.AddAttribute(i++, "class", "rz-dialog-confirm-message"); b.AddContent(i++, message); b.CloseElement(); b.OpenElement(i++, "div"); b.AddAttribute(i++, "class", "rz-dialog-confirm-buttons"); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.OkButtonText); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(true))); b.CloseComponent(); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.CancelButtonText); b.AddAttribute(i++, "ButtonStyle", ButtonStyle.Base); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(false))); b.CloseComponent(); b.CloseElement(); }; return content; }, options, cancellationToken); } /// /// Displays a alert dialog. /// /// The message displayed to the user. /// The text displayed in the title bar of the dialog. /// The options. /// The cancellation token. /// true if the user clicked the OK button, false otherwise. public virtual async Task Alert(string message = "", string title = "Message", AlertOptions? options = null, CancellationToken? cancellationToken = null) { // Validate and set default values for the dialog options options ??= new(); options.OkButtonText = !String.IsNullOrEmpty(options.OkButtonText) ? options.OkButtonText : "Ok"; options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert"; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; options.ContentCssClass = !String.IsNullOrEmpty(options.ContentCssClass) ? $"rz-dialog-content {options.ContentCssClass}" : "rz-dialog-content"; return await OpenAsync(title, ds => { RenderFragment content = b => { var i = 0; b.OpenElement(i++, "p"); b.AddAttribute(i++, "class", "rz-dialog-alert-message"); b.AddContent(i++, message); b.CloseElement(); b.OpenElement(i++, "div"); b.AddAttribute(i++, "class", "rz-dialog-alert-buttons"); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.OkButtonText); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(true))); b.CloseComponent(); b.CloseElement(); }; return content; }, options, cancellationToken); } /// /// Displays a alert dialog. /// /// The message displayed to the user. /// The text displayed in the title bar of the dialog. /// The options. /// The cancellation token. /// true if the user clicked the OK button, false otherwise. public virtual async Task Alert(RenderFragment message, string title = "Message", AlertOptions? options = null, CancellationToken? cancellationToken = null) { // Validate and set default values for the dialog options options ??= new(); options.OkButtonText = !String.IsNullOrEmpty(options.OkButtonText) ? options.OkButtonText : "Ok"; options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : ""; options.Style = !String.IsNullOrEmpty(options.Style) ? options.Style : ""; options.CssClass = !String.IsNullOrEmpty(options.CssClass) ? $"rz-dialog-alert {options.CssClass}" : "rz-dialog-alert"; options.WrapperCssClass = !String.IsNullOrEmpty(options.WrapperCssClass) ? $"rz-dialog-wrapper {options.WrapperCssClass}" : "rz-dialog-wrapper"; options.ContentCssClass = !String.IsNullOrEmpty(options.ContentCssClass) ? $"rz-dialog-content {options.ContentCssClass}" : "rz-dialog-content"; return await OpenAsync(title, ds => { RenderFragment content = b => { var i = 0; b.OpenElement(i++, "p"); b.AddAttribute(i++, "class", "rz-dialog-alert-message"); b.AddContent(i++, message); b.CloseElement(); b.OpenElement(i++, "div"); b.AddAttribute(i++, "class", "rz-dialog-alert-buttons"); b.OpenComponent(i++); b.AddAttribute(i++, "Text", options.OkButtonText); b.AddAttribute(i++, "Click", EventCallback.Factory.Create(this, () => ds.Close(true))); b.CloseComponent(); b.CloseElement(); }; return content; }, options, cancellationToken); } } /// /// Base Class for dialog options /// public abstract class DialogOptionsBase : INotifyPropertyChanged { /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler? PropertyChanged; /// /// Raises the event. /// /// The name of the property that changed. protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool showTitle = true; /// /// Gets or sets a value indicating whether to show the title bar. Set to true by default. /// /// true if title bar is shown; otherwise, false. Default is true. public bool ShowTitle { get => showTitle; set { if (showTitle != value) { showTitle = value; OnPropertyChanged(nameof(ShowTitle)); } } } private bool showClose = true; /// /// Gets or sets a value indicating whether to show the close button. Set to true by default. /// /// true if the close button is shown; otherwise, false. Default is true. public bool ShowClose { get => showClose; set { if (showClose != value) { showClose = value; OnPropertyChanged(nameof(ShowClose)); } } } private string? width; /// /// Gets or sets the width of the dialog. /// /// The width. public string? Width { get => width; set { if (width != value) { width = value; OnPropertyChanged(nameof(Width)); } } } private string? height; /// /// Gets or sets the height of the dialog. /// /// The height. public string? Height { get => height; set { if (height != value) { height = value; OnPropertyChanged(nameof(Height)); } } } private string? style; /// /// Gets or sets the CSS style of the dialog /// /// The style. public string? Style { get => style; set { if (style != value) { style = value; OnPropertyChanged(nameof(Style)); } } } private bool closeDialogOnOverlayClick; /// /// Gets or sets a value indicating whether the dialog should be closed by clicking the overlay. /// /// true if closeable; otherwise, false. public bool CloseDialogOnOverlayClick { get => closeDialogOnOverlayClick; set { if (closeDialogOnOverlayClick != value) { closeDialogOnOverlayClick = value; OnPropertyChanged(nameof(CloseDialogOnOverlayClick)); } } } private string? cssClass; /// /// Gets or sets dialog box custom class /// public string? CssClass { get => cssClass; set { if (cssClass != value) { cssClass = value; OnPropertyChanged(nameof(CssClass)); } } } private string? wrapperCssClass; /// /// Gets or sets the CSS classes added to the dialog's wrapper element. /// public string? WrapperCssClass { get => wrapperCssClass; set { if (wrapperCssClass != value) { wrapperCssClass = value; OnPropertyChanged(nameof(WrapperCssClass)); } } } private string? contentCssClass; /// /// Gets or sets the CSS classes added to the dialog's content element. /// public string? ContentCssClass { get => contentCssClass; set { if (contentCssClass != value) { contentCssClass = value; OnPropertyChanged(nameof(ContentCssClass)); } } } private int closeTabIndex; /// /// Gets or sets a value the dialog escape tabindex. Set to 0 by default. /// public int CloseTabIndex { get => closeTabIndex; set { if (closeTabIndex != value) { closeTabIndex = value; OnPropertyChanged(nameof(CloseTabIndex)); } } } private RenderFragment? titleContent; private bool resizable; /// /// Gets or sets the title content. /// /// The title content. public RenderFragment? TitleContent { get => titleContent; set { if (titleContent != value) { titleContent = value; OnPropertyChanged(nameof(TitleContent)); } } } /// /// Gets or sets a value indicating whether the dialog is resizable. Set to false by default. /// /// true if resizable; otherwise, false. public bool Resizable { get => resizable; set { if (resizable != value) { resizable = value; OnPropertyChanged(nameof(Resizable)); } } } } /// /// Class SideDialogOptions /// public class SideDialogOptions : DialogOptionsBase { private string? title; /// /// The title displayed on the dialog. /// public string? Title { get => title; set { if (title != value) { title = value; OnPropertyChanged(nameof(Title)); } } } private DialogPosition position = DialogPosition.Right; /// /// The Position on which the dialog will be positioned /// public DialogPosition Position { get => position; set { if (position != value) { position = value; OnPropertyChanged(nameof(Position)); } } } private bool showMask = true; /// /// Whether to show a mask on the background or not. Set to true by default. /// public bool ShowMask { get => showMask; set { if (showMask != value) { showMask = value; OnPropertyChanged(nameof(ShowMask)); } } } private bool autoFocusFirstElement; /// /// Gets or sets a value indicating whether to focus the first focusable HTML element. Set to true by default. /// public bool AutoFocusFirstElement { get => autoFocusFirstElement; set { if (autoFocusFirstElement != value) { autoFocusFirstElement = value; OnPropertyChanged(nameof(AutoFocusFirstElement)); } } } private double minWidth = 300.0; /// /// Gets or sets the minimum width (in pixels) enforced while resizing the side dialog. /// public double MinWidth { get => minWidth; set { if (Equals(value, minWidth)) return; minWidth = value; OnPropertyChanged(nameof(MinWidth)); } } private double minHeight = 200.0; /// /// Gets or sets the minimum height (in pixels) enforced while resizing the side dialog. /// public double MinHeight { get => minHeight; set { if (Equals(value, minHeight)) return; minHeight = value; OnPropertyChanged(nameof(MinHeight)); } } private string resizeBarTitle = "Drag to resize"; /// /// Gets or sets the title of the resize bar. /// public string ResizeBarTitle { get => resizeBarTitle; set { if (value == resizeBarTitle) return; resizeBarTitle = value; OnPropertyChanged(nameof(ResizeBarTitle)); } } private string resizeBarAriaLabel = "Resize side dialog"; /// /// Gets or sets the aria label of the resize bar. /// public string ResizeBarAriaLabel { get => resizeBarAriaLabel; set { if (value == resizeBarAriaLabel) return; resizeBarAriaLabel = value; OnPropertyChanged(nameof(ResizeBarAriaLabel)); } } } /// /// DialogPosition enum /// public enum DialogPosition { /// /// Dialog will be positioned on the right side /// Right, /// /// Dialog will be positioned on the left side /// Left, /// /// Dialog will be positioned on the top of the page /// Top, /// /// Dialog will be positioned at the bottom of the page /// Bottom } /// /// Class DialogOptions. /// public class DialogOptions : DialogOptionsBase { /// /// Gets or sets the icon in Title. /// /// The icon. public string? Icon { get; set; } /// /// Gets or sets the icon color in Title. /// /// The icon color. public string? IconColor { get; set; } /// /// Gets or sets the CSS style of the Icon in Title. /// public string IconStyle { get; set; } = "margin-right: 0.75rem"; private Action? resize; /// /// Gets or sets the change. /// /// The change. public Action? Resize { get => resize; set { if (resize != value) { resize = value; OnPropertyChanged(nameof(Resize)); } } } private bool draggable; /// /// Gets or sets a value indicating whether the dialog is draggable. Set to false by default. /// /// true if draggable; otherwise, false. public bool Draggable { get => draggable; set { if (draggable != value) { draggable = value; OnPropertyChanged(nameof(Draggable)); } } } private Action? drag; /// /// Gets or sets the change. /// /// The change. public Action? Drag { get => drag; set { if (drag != value) { drag = value; OnPropertyChanged(nameof(Drag)); } } } private string? left; /// /// Gets or sets the X coordinate of the dialog. Maps to the left CSS attribute. /// /// The left. public string? Left { get => left; set { if (left != value) { left = value; OnPropertyChanged(nameof(Left)); } } } private string? top; /// /// Gets or sets the Y coordinate of the dialog. Maps to the top CSS attribute. /// /// The top. public string? Top { get => top; set { if (top != value) { top = value; OnPropertyChanged(nameof(Top)); } } } private string? bottom; /// /// Specifies the bottom CSS attribute. /// /// The bottom. public string? Bottom { get => bottom; set { if (bottom != value) { bottom = value; OnPropertyChanged(nameof(Bottom)); } } } private RenderFragment? childContent; /// /// Gets or sets the child content. /// /// The child content. public RenderFragment? ChildContent { get => childContent; set { if (childContent != value) { childContent = value; OnPropertyChanged(nameof(ChildContent)); } } } private bool autoFocusFirstElement = true; /// /// Gets or sets a value indicating whether to focus the first focusable HTML element. /// /// true if the first focusable element is focused; otherwise, false. Default is true. public bool AutoFocusFirstElement { get => autoFocusFirstElement; set { if (autoFocusFirstElement != value) { autoFocusFirstElement = value; OnPropertyChanged(nameof(AutoFocusFirstElement)); } } } private bool closeDialogOnEsc = true; /// /// Gets or sets a value indicating whether the dialog should be closed on ESC key press. /// /// true if closeable; otherwise, false. Default is true. public bool CloseDialogOnEsc { get => closeDialogOnEsc; set { if (closeDialogOnEsc != value) { closeDialogOnEsc = value; OnPropertyChanged(nameof(CloseDialogOnEsc)); } } } } /// /// Class ConfirmOptions. /// public class AlertOptions : DialogOptions { private string? okButtonText; /// /// Gets or sets the text of the OK button. /// public string? OkButtonText { get => okButtonText; set { if (okButtonText != value) { okButtonText = value; OnPropertyChanged(nameof(OkButtonText)); } } } } /// /// Class ConfirmOptions. /// public class ConfirmOptions : AlertOptions { private string? cancelButtonText; /// /// Gets or sets the text of the Cancel button. /// public string? CancelButtonText { get => cancelButtonText; set { if (cancelButtonText != value) { cancelButtonText = value; OnPropertyChanged(nameof(CancelButtonText)); } } } } /// /// Class Dialog. /// public class Dialog : INotifyPropertyChanged { private string? title; /// /// Gets or sets the title. /// /// The title. public string? Title { get => title; set { if (title != value) { title = value; OnPropertyChanged(nameof(Title)); } } } private Type? type; /// /// Gets or sets the type. /// /// The type. public Type? Type { get => type; set { if (type != value) { type = value; OnPropertyChanged(nameof(Type)); } } } private Dictionary? parameters; /// /// Gets or sets the parameters. /// /// The parameters. public Dictionary? Parameters { get => parameters; set { if (parameters != value) { parameters = value; OnPropertyChanged(nameof(Parameters)); } } } private DialogOptions? options; /// /// Gets or sets the options. /// /// The options. public DialogOptions? Options { get => options; set { if (options != value) { options = value; OnPropertyChanged(nameof(Options)); } } } /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler? PropertyChanged; /// /// Raises the event. /// /// The name of the property that changed. protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }