Finishing the App

We have a fully functional calculator app, but there are still some things we can do to further customize and refine the app. In this module, we will look at the ThemeService from Uno.Extensions and use this to toggle between light and dark theme in the app. Then we will finish by overriding the default colors to give the app a more custom look and feel.

Adding the ThemeService

We need to update the constructor of our DataContext (MVU Model) to use the IThemeService. First, we need to update the initial value of the IsDark property to use the IThemeServicce.IsDark property. Because the IThemeService may still update the initial theme as initializes, we will want to hook into its ThemeChanged event and update the IsDark property when the theme changes. Finally, we will want to update the theme when the IsDark property is changed by the user.

Update the constructor for the MainModel with the following code:

public MainModel(IThemeService themeService)
{
    Calculator = State.Value(this, () => new Calculator());
    IsDark = State.Value(this, () => themeService.IsDark);

    themeService.ThemeChanged += async (_, _) =>
    {
        // Retrieve the IsDark property whilst still on the UI thread
        var isDark = themeService.IsDark;
        await IsDark.Update(_ => isDark, CancellationToken.None);
    };

    IsDark.ForEachAsync(async (dark, ct) =>
        await themeService.SetThemeAsync(dark ? AppTheme.Dark : AppTheme.Light));
}

With our model updated we need to update our MainPage.xaml.cs file so that we initialize the BindableMainModel with the this.GetThemeService().

public partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        DataContext = new BindableMainModel(this.GetThemeService());
    }
}

Customizing the Color Palette

So far we have the default Uno Material color palette from Uno.Material with some overrides from the new app template. We can further customize the color palette by updating the color overrides in the Styles folder of our SimpleCalculator project.

ColorPaletteOverride.xaml code contents (collapsed for brevity)
<ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Light">
            <!--Background-->
            <Color x:Key="BackgroundColor">#FCFCFF</Color>
            <!--OnBackground-->
            <Color x:Key="OnBackgroundColor">#1A1C1E</Color>
            <!--Primary-->
            <Color x:Key="PrimaryColor">#006399</Color>
            <Color x:Key="PrimaryContainerColor">#CDE5FF</Color>
            <Color x:Key="PrimaryInverseColor">#95CCFF</Color>
            <!--OnPrimary-->
            <Color x:Key="OnPrimaryColor">#FFFFFF</Color>
            <Color x:Key="OnPrimaryContainerColor">#001D32</Color>
            <!--Secondary-->
            <Color x:Key="SecondaryColor">#51606F</Color>
            <Color x:Key="SecondaryContainerColor">#D5E4F6</Color>
            <!--Secondary-->
            <Color x:Key="OnSecondaryColor">#FFFFFF</Color>
            <Color x:Key="OnSecondaryContainerColor">#0E1D2A</Color>
            <!--Tertiary-->
            <Color x:Key="TertiaryColor">#00658D</Color>
            <Color x:Key="TertiaryContainerColor">#C6E7FF</Color>
            <!--OnTertiary-->
            <Color x:Key="OnTertiaryColor">#FFFFFF</Color>
            <Color x:Key="OnTertiaryContainerColor">#001E2D</Color>
            <!--Surface-->
            <Color x:Key="SurfaceColor">#FCFCFF</Color>
            <Color x:Key="SurfaceVariantColor">#DEE3EB</Color>
            <Color x:Key="SurfaceInverseColor">#2F3033</Color>
            <Color x:Key="SurfaceTintColor">#006399</Color>
            <!--OnSurface-->
            <Color x:Key="OnSurfaceColor">#1A1C1E</Color>
            <Color x:Key="OnSurfaceVariantColor">#42474E</Color>
            <Color x:Key="OnSurfaceInverseColor">#F0F0F4</Color>
            <!--Outline-->
            <Color x:Key="OutlineColor">#72777F</Color>
            <Color x:Key="OutlineVariantColor">#C2C7CF</Color>
            <!--Error-->
            <Color x:Key="ErrorColor">#BA1A1A</Color>
            <Color x:Key="ErrorContainerColor">#FFDAD6</Color>
            <!--OnError-->
            <Color x:Key="OnErrorColor">#FFFFFF</Color>
            <Color x:Key="OnErrorContainerColor">#410002</Color>
        </ResourceDictionary>
        <ResourceDictionary x:Key="Dark">
            <!--Background-->
            <Color x:Key="BackgroundColor">#1A1C1E</Color>
            <!--OnBackground-->
            <Color x:Key="OnBackgroundColor">#E2E2E5</Color>
            <!--Primary-->
            <Color x:Key="PrimaryColor">#95CCFF</Color>
            <Color x:Key="PrimaryContainerColor">#004A75</Color>
            <Color x:Key="PrimaryInverseColor">#006399</Color>
            <!--OnPrimary-->
            <Color x:Key="OnPrimaryColor">#003352</Color>
            <Color x:Key="OnPrimaryContainerColor">#CDE5FF</Color>
            <!--Secondary-->
            <Color x:Key="SecondaryColor">#B9C8DA</Color>
            <Color x:Key="SecondaryContainerColor">#3A4857</Color>
            <!--OnSecondary-->
            <Color x:Key="OnSecondaryColor">#233240</Color>
            <Color x:Key="OnSecondaryContainerColor">#D5E4F6</Color>
            <!--Tertiary-->
            <Color x:Key="TertiaryColor">#83CFFF</Color>
            <Color x:Key="TertiaryContainerColor">#004C6B</Color>
            <!--OnTertiary-->
            <Color x:Key="OnTertiaryColor">#00344B</Color>
            <Color x:Key="OnTertiaryContainerColor">#C6E7FF</Color>
            <!--Surface-->
            <Color x:Key="SurfaceColor">#335476</Color>
            <Color x:Key="SurfaceVariantColor">#42474E</Color>
            <Color x:Key="SurfaceInverseColor">#E2E2E5</Color>
            <Color x:Key="SurfaceTintColor">#95CCFF</Color>
            <!--OnSurface-->
            <Color x:Key="OnSurfaceColor">#E2E2E5</Color>
            <Color x:Key="OnSurfaceVariantColor">#C2C7CF</Color>
            <Color x:Key="OnSurfaceInverseColor">#1A1C1E</Color>
            <!--Outline-->
            <Color x:Key="OutlineColor">#8C9198</Color>
            <Color x:Key="OutlineVariantColor">#42474E</Color>
            <!--Error-->
            <Color x:Key="ErrorColor">#FFB4AB</Color>
            <Color x:Key="ErrorContainerColor">#93000A</Color>
            <!--OnError-->
            <Color x:Key="OnErrorColor">#690005</Color>
            <Color x:Key="OnErrorContainerColor">#FFDAD6</Color>
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

With the color palette updated, we can now run the app again to see the updated look for our calculator. The final result will be similar to the image below:

Final Result

Next Steps

Congratulations you have now created your first Uno app! The four permutations of the SimpleCalculator can be found within our Uno.Samples GitHub Repository.

To continue to learn more about Uno Platform be sure to check out the Uno Platform documentation and the Uno Platform samples.

Previous