Creating Custom Controls in .NET MAUI
Custom controls let you encapsulate UI logic, reuse components across pages, and provide a consistent look and feel. This tutorial guides you through building a reusable RatingView
control.
Step 1 – Define the Control
Create a new class that inherits from ContentView
. Add bindable properties for the rating value and the maximum number of stars.
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
namespace MauiApp.Controls
{
public class RatingView : ContentView
{
public static readonly BindableProperty RatingProperty =
BindableProperty.Create(nameof(Rating), typeof(int), typeof(RatingView), 0, propertyChanged: OnRatingChanged);
public static readonly BindableProperty MaxRatingProperty =
BindableProperty.Create(nameof(MaxRating), typeof(int), typeof(RatingView), 5);
public int Rating
{
get => (int)GetValue(RatingProperty);
set => SetValue(RatingProperty, value);
}
public int MaxRating
{
get => (int)GetValue(MaxRatingProperty);
set => SetValue(MaxRatingProperty, value);
}
private readonly StackLayout _starsPanel = new StackLayout { Orientation = StackOrientation.Horizontal };
public RatingView()
{
Content = _starsPanel;
BuildStars();
}
private static void OnRatingChanged(BindableObject bindable, object oldValue, object newValue)
{
((RatingView)bindable).UpdateStars();
}
private void BuildStars()
{
_starsPanel.Children.Clear();
for (int i = 0; i < MaxRating; i++)
{
var tap = new TapGestureRecognizer();
int index = i;
tap.Tapped += (s, e) => Rating = index + 1;
var star = new Image
{
WidthRequest = 32,
HeightRequest = 32,
Aspect = Aspect.AspectFit,
GestureRecognizers = { tap }
};
_starsPanel.Children.Add(star);
}
UpdateStars();
}
private void UpdateStars()
{
for (int i = 0; i < _starsPanel.Children.Count; i++)
{
var img = (Image)_starsPanel.Children[i];
img.Source = i < Rating ? "star_filled.png" : "star_outline.png";
}
}
}
}
Step 2 – Add Resources
Include star_filled.png
and star_outline.png
in the Resources/Images
folder and set their build action to MauiImage
.
Step 3 – Use the Control
Reference the control in XAML and bind its Rating
property.
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MauiApp.Controls;assembly=MauiApp"
x:Class="MauiApp.Pages.RatePage">
<StackLayout Padding="20">
<Label Text="Rate this app:" FontSize="18" />
<controls:RatingView Rating="{Binding UserRating}" />
<Label Text="{Binding UserRating, StringFormat='Your rating: {0}'}" Margin="0,20,0,0" />
</StackLayout>
</ContentPage>
Step 4 – ViewModel
Expose a property in your view model to hold the rating value.
public class RateViewModel : INotifyPropertyChanged
{
private int _userRating;
public int UserRating
{
get => _userRating;
set
{
if (_userRating != value)
{
_userRating = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UserRating)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Result
The control now displays interactive stars. Users can tap a star to set the rating, and the bound view‑model updates automatically.