Skip to content

Application Services

Application Services provide a clean, decoupled way to work with windows, dialogs, and application-wide appearance settings from your ViewModels and business logic. Instead of directly referencing windows and dialogs, or accessing system features, you request these capabilities through well-defined service interfaces. The services handle platform-specific code, while your business logic remains platform-agnostic.

Here is a code snippet that demonstrates the use of the IMessageBoxService to display a message box from a View Model.

using Eremex.AvaloniaUI.Controls.ApplicationServices;

public class MyViewModel
{
    public MyViewModel() { }

    [RelayCommand]
    private void ShowInformation()
    {
        // Access an IMessageBoxService and show a message box.
        var result = Service<IMessageBoxService>()
            .Show("Connection established", "Information", MessageBoxButtons.Ok, MessageBoxIcon.Information);
    }

    // Provides direct access to any service
    protected static T Service<T>() where T : class
        => ApplicationServicesContext.GetRequiredService<T>();
}

Tip

See Access Built-in Services Using the ApplicationServicesContext and SimpleServiceProvider for complete code, which shows how to register built-in services with ApplicationServicesContext.

What You Can Do with Application Services

User Interaction

  • Show standard message boxes with predefined button sets
  • Create custom choice dialogs with application-defined button captions
  • Display modal dialogs driven by ViewModels
  • Show non-modal windows bound to ViewModels

File Operations

  • Open files using the system's file dialog
  • Save files with system dialogs
  • Support both synchronous and asynchronous operations

Window Management

  • Get the active window from anywhere in your code
  • Automatically set the owner for dialogs

Appearance and Theming

  • Get available theme options
  • Create a theme selector in your UI

Available Services

The Eremex Controls library contains the following services, each providing a specific capability.

User Interaction Services

Service Description
IMessageBoxService Shows standard message boxes with fixed button sets defined by the MessageBoxButtons enumeration (Ok, Ok|Cancel, Yes|No|Cancel, Yes|No, Abort|Retry|Ignore, and Retry|Cancel).
IDialogService Shows dialogs from ViewModel code, so that a ViewModel can ask the user a question without referencing any window type. A dialog is driven by a dialog ViewModel. You can also implement a View to display as the dialog's content. This View is located through the ViewLocatorAttribute applied to the dialog ViewModel.
IChoiceDialogService Shows a dialog with an arbitrary set of buttons and returns the result of the pressed one.
IWindowService Shows non-modal windows from ViewModel code, so that a ViewModel can open a window without referencing any window type. The counterpart for modal dialogs is IDialogService.

File Services

Service Description
IOpenFileDialogService Shows the platform Open File dialog from ViewModel code in sync or async mode.
ISaveFileDialogService Shows the platform Save File dialog from ViewModel code in sync or async mode.

Infrastructure Services

Service Description
IWindowsManager Tracks the active window of the application. Dialog services use the IWindowsManager service to get the default owner for newly created dialogs.
IAppearanceService Provides access to available visual theme settings and allows you to change the current theme options.

Use Services

You can use the ApplicationServicesContext and SimpleServiceProvider classes to work with built-in services, or use custom DI containers.

Access Built-in Services Using the ApplicationServicesContext and SimpleServiceProvider

Register the built-in services with the SimpleServiceProvider and ApplicationServicesContext when the application starts (in the App class). Then create a convenient Service<T>() helper method in your ViewModel to access these services using the ApplicationServicesContext.GetRequiredService<T> method.

using Eremex.AvaloniaUI.Controls.ApplicationServices;

public abstract partial class ApplicationServicesPageViewModelBase : PageViewModelBase
{
    // Provides direct access to any service
    protected static T Service<T>() where T : class
        => ApplicationServicesContext.GetRequiredService<T>();
}

public partial class MyViewModel : ApplicationServicesPageViewModelBase
{
    [RelayCommand]
    private void ShowInformation()
    {
        // Access an IMessageBoxService and show a message box.
        var result = Service<IMessageBoxService>()
            .Show("Connection established", "Information", MessageBoxButtons.Ok, MessageBoxIcon.Information);
    }
}

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);
    }

}

The SimpleServiceProvider is a minimal IServiceProvider implementation that requires no external NuGet packages. It is a lightweight, thread-safe container intended for applications and tests that do not need a full DI container. All services are created lazily and live as singletons (created once and cached for the application lifetime). Created instances implementing IDisposable are disposed by the Dispose method.

Access Services Through Constructor Injection

You can pass an application service to a ViewModel directly through its constructor. Then you can call a method of this service in the ViewModel.

public partial class MyViewModel
{
    private readonly IMessageBoxService messageBoxService;

    public MyViewModel(IMessageBoxService messageBoxService)
    {
        this.messageBoxService = messageBoxService;
    }

    [RelayCommand]
    private void ShowInformation()
    {
        var result = messageBoxService.Show("Connection established", "Information", MessageBoxButtons.Ok, MessageBoxIcon.Information);
    }
}

Custom Dependency Injection Container Support

If you use an external DI container, register the built-in services with it and set the resulting provider as the current one.

  • Microsoft.Extensions.DependencyInjection

    var services = new ServiceCollection();
    services.AddTransient<IDataService, DataService>();
    ApplicationServicesContext.RegisterApplicationServices(
        (type, factory) => services.AddSingleton(type, sp => factory(sp))
    );
    var provider = services.BuildServiceProvider();
    ApplicationServicesContext.SetCurrent(provider);
    
  • Autofac

    var services = new ServiceCollection();
    services.AddTransient<IDataService, DataService>();
    //...
    var builder = new ContainerBuilder();
    builder.Populate(services);
    ApplicationServicesContext.RegisterApplicationServices(
        (type, factory) => builder
            .Register(c => factory(c.Resolve<IServiceProvider>()))
            .As(type)
            .SingleInstance()
    );
    var container = builder.Build();
    var serviceProvider = new AutofacServiceProvider(container);
    ApplicationServicesContext.SetCurrent(serviceProvider);
    
  • Custom IServiceProvider implementations

    You can implement IServiceProvider yourself and pass it to ApplicationServicesContext.SetCurrent.