Skip to content

IAppearanceService

IAppearanceService provides a platform-agnostic way to access the appearance choices supported by the DeltaDesign theme and apply the chosen one. It allows your ViewModel to change the theme variant, color palette, and layout density at runtime without referencing any UI framework type directly.

Main features include:

  • Theme variants — Provides access to available theme variants (Light and Dark).
  • Color palettes — Provides access to the color palettes in the DeltaDesign theme, such as Nova, Helios, Terra, Vega, and Atlas.
  • Layout densities — Provides access to the layout densities available in the DeltaDesign theme (Compact, Standard, and Spacious).
  • Immediate application — You can change a dedicated option of IAppearanceService to immediately change the corresponding theme setting.
  • Bindable to selectors — The service implements the INotifyPropertyChanged interface and is designed to be bound directly to a ribbon gallery, a combo box, a menu, or any other selector.

Interface Definition

public interface IAppearanceService : INotifyPropertyChanged
{
    // A list of available theme variants (light/dark).
    IReadOnlyList<IAppearanceOption> ThemeVariants { get; }

    // A list of available color palettes.
    IReadOnlyList<IAppearanceOption> Palettes { get; }

    // A list of availalbe layout densities.
    IReadOnlyList<IAppearanceOption> Densities { get; }

    // The chosen theme variant. Assigning it recolors the running application at once.
    IAppearanceOption SelectedThemeVariant { get; set; }

    // The chosen theme palette. Assigning it recolors the running application at once.
    IAppearanceOption SelectedPalette { get; set; }

    // The chosen density. Assigning it resizes the controls of the running application at once.
    IAppearanceOption SelectedDensity { get; set; }
}

IAppearanceOption

Each item in the ThemeVariants, Palettes, and Densities lists implements the IAppearanceOption interface:

public interface IAppearanceOption
{
    // The text shown for this choice.
    string Header { get; }
}

All service interfaces are free of references to UI framework types. The IAppearanceOption interface follows the same principle. It only contains a string property that specifies the caption of a theme option. However, actual implementations of the IAppearanceOption interface return richer objects, listed below:

IAppearanceOption Implementation Description
ThemeOption class A light or dark theme variant. Additional properties include:
- ThemeOption.Variant (of the Avalonia.Styling.ThemeVariant type) — the theme variant associated with this option.
PaletteOption class A color palette. Additional properties include:
- PaletteOption.Palette — the palette applied when this option is chosen (Nova, Helios, Terra, Vega, Atlas, etc.);
- PaletteOption.Accent — a read-only Brush object that represents the current palette. The PaletteOption.Accent property allows you to show a color swatch in a selector, so the user can preview a palette before picking it.
DensityOption class A layout density. Additional properties include:
- DensityOption.Density — the density applied when this option is chosen (Compact, Standard, or Spacious).

These objects are returned by the IAppearanceService actual implementation. For instance, the actual return value of IAppearanceService.SelectedPalette is a PaletteOption object.

How to Use IAppearanceService

  1. In your ViewModel, expose the IAppearanceService service as a property.
  2. In your View, bind your selector controls to the members of this property.

Access the Service

You need to access the IAppearanceService service in your ViewModel to expose it as a property.

There are two ways to access an IAppearanceService 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.

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

    public IAppearanceService Appearance { get; } = Service<IAppearanceService>();
}

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 IAppearanceService as a parameter. When you instantiate the ViewModel, pass the service object to this constructor.

public partial class MainViewModel : ObservableObject
{
    public MainViewModel(IAppearanceService appearance)
    {
        Appearance = appearance;
    }

    public IAppearanceService Appearance { get; }
}

Expose the Service from the ViewModel

Expose IAppearanceService as a public property. UI controls in the View will bind to it directly:

The following example creates the Appearance property of the IAppearanceService type and initializes it using the Service<T> helper.

public partial class MainViewModel : ObservableObject
{
    public IAppearanceService Appearance { get; }

    public MainViewModel(ThemeVariant? startupThemeVariant = null)
    {
        Appearance = Service<IAppearanceService>();
        Appearance.SelectedThemeVariant = FindTheme(startupThemeVariant);
        //...
    }

    private IAppearanceOption? FindTheme(ThemeVariant? variant)
        => variant is null
            ? null
            : Appearance.Themes.FirstOrDefault(
                x => string.Equals(x.Header, variant.ToString(), StringComparison.OrdinalIgnoreCase));

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