András Tóth‘s professional blog
banditoth.net

Hey there 👋, I’m banditoth a .NET MAUI developer from Hungary.
I write about software development with .NET technologies.

You can find me on:
LinkedIn | Github | StackOverflow | X / Twitter | Threads

Tag: .NET MAUI

  • .NET MAUI: Implementing Light and Dark Modes

    This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    In modern application development, providing users with the ability to switch between light and dark modes has become an essential feature. This functionality not only enhances user experience but also accommodates personal preferences and improves accessibility. In this blog post, we will explore how to implement light and dark modes in .NET MAUI apps using the UserAppTheme property in the App.xaml.cs file.

    Understanding the App.xaml.cs File

    The App.xaml.cs file in a .NET MAUI application is responsible for defining the application’s startup and initialization logic. It acts as the entry point for the application and provides a central location to handle events and configure application-wide settings.

    Setting the UserAppTheme Property

    To enable light and dark modes in your .NET MAUI app, you need to access the UserAppTheme property available in the Application.Current object. This property allows you to specify the desired theme for your application.

    If your application does not allow the users to change the light/dark modes, but you want to force the app to be in a specified state, you can use the App.xaml.cs constructor, and you can set the UserAppTheme property to either AppTheme.Light or AppTheme.Dark, depending on a predefined default.

    Here’s an example of how to set the AppTheme to Light mode:

    Application.Current.UserAppTheme = AppTheme.Light;

    Similarly, you can set the AppTheme to Dark mode:

    Application.Current.UserAppTheme = AppTheme.Dark;
  • .NET MAUI: Save any type of object in Preferences

    This content has 2 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    .NET MAUI currently have limitations of the supported types in preferences. They can only store simple data types such as strings, integers, and booleans, and do not support more complex data types such as lists or objects. This can make it difficult to store and retrieve more complex data structures.

    How to store arrays and lists, or complex classes in Preferences?

    The answer is currently to serialize it. Since Preferences is supporting string saving option, you can serialize your arrays and custom classes, and store the string value.

    But be aware to store large amounts of data in Preferences as a string. Consider choosing SQLite to store data when there are more than 50-100 items in an array, or your class is more complex than having 25 properties. As Microsoft marks this as a limitation: Performance may be impacted if you store large amounts of text, as the API was designed to store small amounts of text.

    But there are cases when it makes sense to store other types

    There are cases when it is easier to store a whole complex object on disk than to store all its properties one by one by calling preferences Set. In this case you may find useful the banditoth.MAUI.PreferencesExtension.

    Usage

    This package is extending the basic functions of the built in MAUI Essentials IPreferences by letting the developers to save any type of object. This is done by using JSON serialization, and saving the raw jsons as strings with the default IPreferences implementation. Since JSON arrays can be serialized back to any collection type, you can use different types when Setting the value and when Getting it back.

    There are several ways to access this extension.

    Dependency Injection

        private readonly IPreferences preferences;
    
        public MainPage(IPreferences preferences)
        {
            InitializeComponent();
            this.preferences = preferences;
        }
    
        private void Foo()
        {
            List<string> taleItems = new List<string>()
            {
                "The quick brown fox",
                "Jumps over the lazy dog"
            };
    
            preferences.SetObject<List<string>>("Tale", taleItems);
    
            string[] taleItemsFromPreferences = preferences.GetObject<string[]>("Tale", null);
        }
    

    Access through Preferences

    If you are used to access the preferences trough the static class, you can use this tool by accessing the Default property on the Preferences class. You can call the SetObject or GetObject extension method on it.

                // Setting the value
                Preferences.Default.SetObject<IDeviceInfo>("Device_Information", DeviceInfo.Current);
                // Getting the value
                Preferences.Default.GetObject<IDeviceInfo>("Device_Information", null);
    

    Package’s own static reference

    You can also access the SetObject or GetObject method on PreferencesExtension static class.

                // Setting the value
                PreferencesExtension.SetObject<DisplayOrientation>("Last_Display_Orientation", orientation);
                // Getting the value
                PreferencesExtension.GetObject<DisplayOrientation>("Last_Display_Orientation", DisplayOrientation.Landscape);
    
  • Configure CI pipeline with .NET MAUI Release candidate (for NuGets)

    This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    In order to do automated builds in Azure DevOps with the .NET MAUI Release Candidate release, we need a few extra steps in the pipeline configuration. I used these steps to ensure that the NuGet packages I develop are automatically compiled and uploaded to NuGet.org. In this article I won’t go into detail about how to create a CI pipeline, I just want to show you the difference from a normal CI pipeline. I haven’t tried building and deploying applications in the cloud at the moment, but it can probably be done. Also, I don’t go into how to make the package automatically go to NuGet.org, for that I recommend an earlier article (and also how to create a CI/CD pipeline): https://www.banditoth.net/2021/11/09/azure-devops-setup-private-nuget-feed-with-ci/

    Since a final version of .NET MAUI has not been released as of today, in order to build our applications in the cloud, we need to install the MAUI Workload on the Agent.
    If we do not do this, we may encounter the following error:

    Error NETSDK1147: To build this project, the following workloads must be installed: maui-windows
    

    Adjust your pipeline

    In order to install the workload on our build agent, create a new task at the very beginning in the pipeline file, which is executes a command in the command line:

    This will result the following task in the yaml file:

    - task: CmdLine@2
      inputs:
        script: 'dotnet workload install maui'
    

    The installation of the workload will take about 5 minutes.

    From now on, you will be able to use .NET Maui references on the pipelines too. This will let you build your packages in the cloud.
    Once MAUI will be officially available, probably you don’t need these steps.

  • The easiest and best MVVM toolkit also for .NET MAUI.

    This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Guys, this is unbelievable. Microsoft Community toolkit has added a tool that means you never have to worry about which MVVM framework you’re voting for. None can be as good as this one. It can be used not only for .NET MAUI, but also for other technologies (e.g. WPF). But before I sing your praises, let’s look at what this package has to offer us:

    Introducing CommunityToolkit.Mvvm

    First of all, you don’t need to implement INotifyPropertyChanged in ViewModels. And by that I mean not even its parent classes. Since this component is a code generator, it’s enough to make your classes partial, and the INotifyPropertyChanged implementation is done by it, instead of you. This means that your class will be supplemented with the best implementation so that you can easily use common methods like SetProperty in the setter branch of your properties. Okay, okay, but almost any MVVM framework could do this, and you didn’t even need to use a code generator, just simply derive from a parent class. I’ll do you one better: what if you didn’t have to write the setter and getter branches of the properties at all? What if the toolkit made them itself? If you could implement a property declaration from two lines of code?
    Well, that’s what makes this toolkit good: It does all that for you.

    And if that’s not enough, you don’t even have to bother creating Commands. The toolkit automatically creates a command for you from your methods.
    But let’s see how you can use it.

    Use CommunityToolkit.MVVM in .NET MAUI

    Let’s see what my ViewModel looked like before I used this toolkit:

    namespace Carloo.ViewModels.SignInPage
    {
        public partial class SignInPageViewModel : BaseViewModel
        {
            private Command signInCommand;
            public Command SignInCommand
            {
                get { return signInCommand ?? (signInCommand = new Command(() => _ = SignIn(), () => true)); }
            }
    
            private string userName;
            public string UserName
            {
                get { return userName; }
                set { SetProperty(ref userName, value, nameof(UserName)); }
            }
    
            private string password;
            public string Password
            {
                get { return password; }
                set { SetProperty(ref password, value, nameof(Password)); }
            }
    
            public SignInPageViewModel()
            {
    
            }
    
            private void SignIn()
            {
                try
                {
                    ...
                }
                catch (Exception ex)
                {
                    // todo error
                }
            }
        }
    }
    
    

    And now let’s see what this Toolkit can do with source code to make life easier:

    namespace Carloo.ViewModels.SignInPage
    {
        [INotifyPropertyChanged]
        public partial class SignInPageViewModel
        {
            [ObservableProperty]
            private string userName;
    
            [ObservableProperty]
            private string password;
    
            public SignInPageViewModel()
            {
    
            }
    
            [ICommand]
            private void SignIn()
            {
                try
                {
                    ...
                }
                catch (Exception ex)
                {
                    // todo error
                }
            }
        }
    }
    
    

    In other ways, however, Resharper also had the tools to provide similar simplicity for implementing MVVM. But if I remember correctly, it didn’t have all that. Like, say, that you could release PropertyChanged on a completely unrelated property, even with an attribute declaration, without writing code.

            [ObservableProperty]
            [AlsoNotifyFor(nameof(CanSignIn))]
            private string _userName;
    
            [ObservableProperty]
            [AlsoNotifyFor(nameof(CanSignIn))]
            private string _password;
    
    
            public bool CanSignIn { get => !string.IsNullOrWhiteSpace(UserName) && !string.IsNullOrWhiteSpace(Password); }
    

    Learn more

    I am very excited about using this tool in production environments. If you want to learn more about it, please visit the following pages:
    https://devblogs.microsoft.com/ifdef-windows/announcing-net-community-toolkit-v8-0-0-preview-1/
    https://docs.microsoft.com/en-gb/windows/communitytoolkit/mvvm/introduction

  • .NET MAUI: App.xaml, MainPage.xaml is missing from the project

    This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    .NET MAUI is still in beta so there are no final project templates to create a new MAUI application. The current project template omits the App.xaml, and MainPage.xaml files from the project (at least on mac), so we have to add them ourselves.

    Enable on Visual Studio, to show all files

    Enable showing all files

    And select the missing files, then right click on them, and add them to the project.

    Include the missing files to the project