IChoiceDialogService¶
IChoiceDialogService provides a platform-agnostic way to show a modal dialog with an arbitrary set of buttons and return the result of the pressed one. The dialog result can be a string, bool, enumeration value, or any other type. From your ViewModel, you can use IChoiceDialogService to display a dialog and receive a strongly typed answer, without referencing any window type.
Main features include:
- Dialog is automatically closed when one of its choice buttons (shown in the dialog's footer) is clicked.
- Any number of choice buttons — For each button you can specify a caption and associate it with a dialog result, returned when this button is pressed.
- Dialog result — The dialog result is specified by a clicked button's
Resultvalue, which can be astring, abool, an enumeration, or any other type. - Customizable button placement — Dialog buttons support the
Dockproperty which allows you to forcibly place buttons first or last. - Default button — You can mark a specific button as default. When the user presses ENTER, the dialog invokes this button's command.
- Cancel button — Mark any button with
IsCancelto make it respond to ESC. - Automatic owner — The owner window is resolved by the underlying
IDialogServicethroughIWindowsManager, so it does not need to be specified explicitly. - Choice buttons are always enabled — Unlike IDialogService, which supports
CanOkfor validation,IChoiceDialogServicehas no mechanism to disable individual choices based on input state.
Interface Definition¶
public interface IChoiceDialogService
{
// Show a modal dialog with the given choices.
T Show<T>(string message, string? caption, IReadOnlyList<DialogChoice<T>> choices);
}
| Parameter | Type | Description |
|---|---|---|
message |
string |
The dialog's body content assigned to the dialog ViewModel's Content property. Cannot be null. |
caption |
string? |
The dialog's caption. When set to null, the caption is taken from the dialog ViewModel's Title property. |
choices |
IReadOnlyList<DialogChoice<T>> |
The available choices displayed as buttons in the dialog's footer. The order matches the button order. Cannot be null and must contain at least one item. |
Returns:
T— the result associated with the clicked choice buttondefault(T)if the dialog was closed without a choice by clicking the dialog's caption 'x' button.default(T)isnullfor reference types (includingstring),falsefor thebooltype,0for an enum without an explicit zero member.- Pressing ENTER — If the dialog contains a choice button with
IsDefault = true, pressing ENTER returns that button'sResultvalue. If no choice button hasIsDefault = true, pressing ENTER does nothing, and the dialog remains open. - Pressing ESC — If the dialog contains a choice button with
IsCancel = true, pressing Escape returns that button'sResultvalue. If no choice button hasIsCancel = true, pressing Escape does nothing, and the dialog remains open.
See also: Handle a Dismissed Dialog.
Exceptions:
ArgumentNullException— Themessageorchoicesparameter isnull.ArgumentException— Thechoiceslist is empty. A dialog must contain at least one button.
DialogChoice¶
Each choice button in the dialog is described by a DialogChoice<T> instance:
public sealed class DialogChoice<T>
{
// The button caption.
public string Caption { get; }
// The result returned by the `IChoiceDialogService.Show` method when the button is pressed.
public T Result { get; }
// Whether the current button is the default button, invoked by Enter.
public bool IsDefault { get; set; }
// Whether the current button is the cancel button, invoked by Escape.
public bool IsCancel { get; set; }
// The side to which the button is docked. Defaults to `DockType.Right`.
public DockType Dock { get; set; } = DockType.Right;
// The button order within its side. Use the `Index` property when you need to reorder buttons without changing the button array.
public int? Index { get; set; }
public DialogChoice(string caption, T result);
}
How to Use IChoiceDialogService¶
In your ViewModel, call the IChoiceDialogService.Show method to display the dialog with specified choice buttons. The method returns the Result value of the pressed choice button.
Access the Service¶
There are two ways to access an IChoiceDialogService object in a ViewModel:
- Through the
Service<T>()helper method. This is a convenient approach to obtain registered application services shipped with the Eremex Controls library. - Through constructor injection.
Service() Helper¶
Implement a helper Service<T>() method in your ViewModel to get a requested service using the static ApplicationServicesContext.GetRequiredService<T>() method.
Example - Show a Dialog Using Service() Helper¶
using Eremex.AvaloniaUI.Controls.ApplicationServices;
using CommunityToolkit.Mvvm.Input;
public partial class MyViewModel : ObservableObject
{
// Provides access to any registered service
protected static T Service<T>() where T : class
=> ApplicationServicesContext.GetRequiredService<T>();
[RelayCommand]
private void ShowChoiceDialog()
{
// Resolve the service and show the dialog
var result = Service<IChoiceDialogService>().Show(
"The license server did not respond.",
"Activation failed",
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
if(result == "retry")
{
//...
}
else
{
//...
}
}
}
In the App.axaml.cs file, ensure that Eremex application services are registered using SimpleServiceProvider and ApplicationServicesContext as follows:
public class App : Application
{
public override void OnFrameworkInitializationCompleted()
{
RegisterApplicationServices();
//...
}
static void RegisterApplicationServices()
{
// Register built-in services.
var serviceProvider = new SimpleServiceProvider();
ApplicationServicesContext.RegisterApplicationServices(serviceProvider.AddSingleton);
ApplicationServicesContext.SetCurrent(serviceProvider);
}
}
Constructor Injection¶
Implement a constructor in your ViewModel with IChoiceDialogService as a parameter. When you instantiate the ViewModel, pass the service object to this constructor.
public partial class MyViewModel
{
private readonly IChoiceDialogService _choiceDialogService;
public MyViewModel(IChoiceDialogService choiceDialogService)
{
_choiceDialogService = choiceDialogService;
}
[RelayCommand]
private void ShowChoiceDialog()
{
var result = _choiceDialogService.Show(
"The license server did not respond.",
"Activation failed",
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
//...
}
}
Return a String Result¶
To return a string value when a dialog button is clicked, use DialogChoice<string> for that button. The value associated with this button is specified by the result parameter of the DialogChoice<T> constructor.
The following example shows a dialog with three buttons. Specific dialog results (string values — "log", "retry", and "close") are associated with these buttons. The dialog's Show method returns a corresponding value when one of its buttons is clicked.
[RelayCommand]
private void ShowDialogWithCustomCaptions()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
}
Return a Boolean Result¶
To return a Boolean value when a dialog button is clicked, use DialogChoice<bool> for that button. The value associated with this button is specified by the result parameter of the DialogChoice<T> constructor.
The following example shows a dialog with two buttons. Specific dialog results (true and false) are associated with these buttons. The dialog's Show method returns a corresponding value when one of its buttons is clicked.
[RelayCommand]
private void ShowDialogWithBooleanResult()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<bool>("Show log", true) { IsDefault = true },
new DialogChoice<bool>("Close", false) { IsCancel = true },
});
}
See also: Handle a Dismissed Dialog.
Return an Enum Result¶
To return an enumeration value when a dialog button is clicked, use DialogChoice< enum > for that button. The value associated with this button is specified by the result parameter of the DialogChoice<T> constructor.
The following example shows a dialog with three buttons. Specific dialog results (DialogResult.Abort, DialogResult.Retry, and DialogResult.Ignore) are associated with these buttons. The dialog's Show method returns a corresponding value when one of its buttons is clicked.
[RelayCommand]
private void ShowDialogWithEnumResult()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<DialogResult>("Abort", DialogResult.Abort) { IsCancel = true },
new DialogChoice<DialogResult>("Retry", DialogResult.Retry) { IsDefault = true },
new DialogChoice<DialogResult>("Ignore", DialogResult.Ignore),
});
}
Set Button Placement¶
Use the DialogChoice<T>.Dock property to forcibly position specific buttons first (set the Dock property to DockType.Left) or last (set the Dock property to DockType.Right) among all buttons. The Dock property defaults to DockType.Right.
[RelayCommand]
private void ShowDialogWithCustomButtonPlacement()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<string>("Help", "help") { Dock = DockType.Left },
new DialogChoice<string>("Retry", "retry") { IsDefault = true },
new DialogChoice<string>("Cancel", "cancel") { IsCancel = true },
});
}
Handle a Dismissed Dialog¶
When the user dismisses the dialog by clicking the caption 'x' button, the Show method returns default(T):
- For reference types (
string, etc.), the result isnull. - For value types (
bool, enums, etc.), the result is the default value of the type (falsefor a Boolean type,0for an enumeration, etc.)
If the dialog contains a cancel button (a choice button whose IsCancel property is true), clicking it or pressing Escape closes the dialog with that button's result. The caption 'x' button still closes the dialog with the default(T) result.
Example — Handle a Dialog's Dismissal¶
The following example creates a dialog with a cancel button associated with the null dialog result. In this case, you only need to check for the null dialog result to handle all dialog dismissal scenarios:
- The cancel button is clicked.
- The
xcaption button is clicked. - The Escape key is pressed.
var result = Service<IChoiceDialogService>().Show(
"Save the document?",
"Confirmation",
new[]
{
new DialogChoice<bool?>("Yes", true) { IsDefault = true },
new DialogChoice<bool?>("No", false),
new DialogChoice<bool?>("Cancel", null) { IsCancel = true },
});
if (result is null)
{
// Dialog was dismissed or Cancel was clicked, or Escape was pressed.
}
else if (result.Value)
{
// Yes was pressed.
}
else
{
// No was pressed.
}