How to create a "singleton" reusable content view in .NET MAUI?

503 Views Asked by At

I am new in .NET MAUI universe. Still exploring and understanding somethings. I have a question about a way to create a reusable component shared by different Content Pages, for example a Score Bar for a game that contains different Content Pages (Views).

Look the example below:

enter image description here

For this application I have created 3 different Content Pages:

  • Home
  • Play
  • Tutorial

They have a common component (Score Bar) highlighted in the image and defined as a Content View. This way I am able to reuse the component between all the Content Pages, but I would like to keep it always updated as a Singleton component, because this way if I change the Score defined in "Score bar" it would be affected in all pages.

As I have implemented the ScoreBar is reusable but different (with different values) for each ContentPage, like having different instance by each View.

I have tried an idea shared in this video "Master Content Page ( Master Page, Partial View ) In .NET MAUI / Xamarin" as well, keeping my ScoreBar in the MasterPage but the TemplateBinding did not work properly for me and RelativeBindingSource neither, maybe because I am using MAUI 8 preview.

I have injected a ScoreService in my ViewModels and created a WeakMessage to update my ScoreBar always when needed. But it still does not look the best way in my opinion because the ScoreBar should be shared between all pages with the same status, not as different "instances".

Do you have any idea how to apply it? Is it possible in .NET MAUI?

Thanks in advance.

1

There are 1 best solutions below

1
On

One possible solution

  1. Write ScoreService.

Add method to increase score, to reset score, to convert score to display string. You can have it injected as singleton and store the data in the service iteself, or have the service transient, and some sort of repository to deal with the data. The second choice is what I would do, but for your project it is overkill.

To make the score observable, you can always bind to a property that calls those service methods, and fire events together with adding score.

  1. Write ControlTemplate.

Open your App.xaml, add ControlTemplate, Add Grid with two columns (based on your screenshot), set its BindingContext like that:

BindingContext="{Binding Source={RelativeSource TemplatedParent}}"

Add some Labels, set their Text to { Binding SomeProperty }.

  1. Create your own custom control

    public class ScoreView : ContentView

Add a bindable property to it. (SomeProperty from step 2.)

Done.

All you have to reuse this control everywhere is to go to the page xaml, and do something like:

<controls: ScoreView ControlTemplate="{StaticResource ScoreControlTemplate}"
                     SomeProperty="{Binding Score}"/>

This way you can make your custom controls change any time. The technical logic of the control stays in the cs file for ScoreView. The business logic stays in the ViewModel, the way you present data stays in the template. One instance of code per project.