🧭 Introduction
When building cross-platform apps with .NET MAUI (Multi-platform App UI), you’ll often find yourself repeating UI patterns — like custom buttons, input fields, or layouts — across multiple pages.
That’s where custom controls come in.
Custom controls in .NET MAUI let you:
- Reuse UI logic and layout across pages and projects
- Simplify maintenance
- Improve code readability and consistency
In this tutorial, we’ll explore how to create, use, and style a custom control in .NET MAUI — step by step.
🛠️ Prerequisites
Before we start, make sure you have:
- .NET 8 SDK (or later)
- Visual Studio 2022 (17.8 or newer)
- A .NET MAUI App template created (
dotnet new maui -n MauiCustomControlDemo)
🚀 Step 1: Understanding the Types of Custom Controls
In .NET MAUI, you can create custom controls in three main ways:
- User Controls (Composable Controls) – built using XAML and C#, perfect for combining existing controls.
- Templated Controls – fully customizable look & feel, defined by ControlTemplates.
- Drawn Controls (Graphics) – for creating highly customized visuals using
Microsoft.Maui.Graphics.
In this tutorial, we’ll start with the most common type — a User Control.
🎨 Step 2: Create a Custom User Control
Let’s create a custom control called RoundedButton.
🧩 Step 2.1: Add a New ContentView
In Visual Studio, right-click on your project →
Add → New Item → .NET MAUI → ContentView (XAML)
Name it:
RoundedButton.xaml
You’ll get two files:
RoundedButton.xamlRoundedButton.xaml.cs
🧱 Step 2.2: Define the UI (XAML)
Open RoundedButton.xaml and replace its content with:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiCustomControlDemo.Controls.RoundedButton">
<Frame
Padding="10"
CornerRadius="25"
BackgroundColor="{Binding BackgroundColor, Source={x:Reference Root}}"
HasShadow="True">
<Label
Text="{Binding Text, Source={x:Reference Root}}"
TextColor="{Binding TextColor, Source={x:Reference Root}}"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Frame>
</ContentView>
Here, we used a Frame with a rounded corner radius, and a Label to show button text.
⚙️ Step 2.3: Add Properties (Code-behind)
Now open RoundedButton.xaml.cs and add the following:
using Microsoft.Maui.Controls;
namespace MauiCustomControlDemo.Controls;
public partial class RoundedButton : ContentView
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(RoundedButton), default(string));
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(RoundedButton), Colors.White);
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(RoundedButton), Colors.Blue);
public event EventHandler? Clicked;
public RoundedButton()
{
InitializeComponent();
// Add gesture recognizer for click
var tapGesture = new TapGestureRecognizer();
tapGesture.Tapped += (s, e) => Clicked?.Invoke(this, EventArgs.Empty);
GestureRecognizers.Add(tapGesture);
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public Color TextColor
{
get => (Color)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}
public new Color BackgroundColor
{
get => (Color)GetValue(BackgroundColorProperty);
set => SetValue(BackgroundColorProperty, value);
}
}
This creates bindable properties for Text, TextColor, and BackgroundColor, plus a click event.
🧩 Step 3: Use the Custom Control in a Page
Open MainPage.xaml and use your control like this:
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MauiCustomControlDemo.Controls"
x:Class="MauiCustomControlDemo.MainPage">
<VerticalStackLayout Padding="30" Spacing="20">
<controls:RoundedButton
Text="Tap Me!"
BackgroundColor="MediumPurple"
TextColor="White"
Clicked="OnRoundedButtonClicked" />
</VerticalStackLayout>
</ContentPage>
And handle the click in MainPage.xaml.cs:
private void OnRoundedButtonClicked(object sender, EventArgs e)
{
DisplayAlert("Clicked!", "You tapped the custom button!", "OK");
}
🧠 Step 4: Styling the Control (Optional)
You can easily apply a Style in Resources/Styles.xaml:
<Style TargetType="controls:RoundedButton">
<Setter Property="BackgroundColor" Value="Teal" />
<Setter Property="TextColor" Value="White" />
</Style>
This keeps your custom controls consistent across your app.
🪄 Step 5: Going Further — Create a Templated Control
If you want a more flexible and reusable control that users can restyle completely, you can create a Templated Control by inheriting from TemplatedView instead of ContentView.
You’d define a ControlTemplate that consumers can override — perfect for creating components like custom entries, toggle buttons, or complex cards.
🎯 Conclusion
You’ve just built your first custom control in .NET MAUI!
Now you can reuse this control across your entire app — and even publish it as a NuGet package for others to use.
Key Takeaways:
- Use
ContentViewfor simple composable controls. - Use
TemplatedViewfor advanced, skinnable controls. - Bindable properties make your controls reusable and powerful.
💡 What’s Next?
- Try adding animation when the button is tapped.
- Create a custom input control (like a search bar).
- Package your control into a .NET MAUI library project.

Leave a Reply