| MAUI-CommunityToolkit-9 :👈 | 👉:MAUI-CommunityToolkit-11 |
Hour 10 โ Advanced MAUI UI, Custom Controls & Bindable Properties |
Welcome to Hour 10 of the MAUI MVVM learning series. Today, we explore more advanced UI concepts in MAUI, including:
MAUI allows you to create your own reusable UI components using ContentView. These help avoid duplicated UI logic.
<!-- MyCardView.xaml -->
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:Class="MyApp.Controls.MyCardView">
<Frame Padding="20" BackgroundColor="LightGray">
<StackLayout>
<Label x:Name="TitleLabel" FontSize="20" />
<Label x:Name="SubtitleLabel" FontSize="14" />
</StackLayout>
</Frame>
</ContentView>
// MyCardView.xaml.cs
public partial class MyCardView : ContentView
{
public static readonly BindableProperty TitleProperty =
BindableProperty.Create(nameof(Title), typeof(string),
typeof(MyCardView), string.Empty, propertyChanged: OnTitleChanged);
public string Title
{
get => (string)GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
private static void OnTitleChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (MyCardView)bindable;
control.TitleLabel.Text = (string)newValue;
}
public static readonly BindableProperty SubtitleProperty =
BindableProperty.Create(nameof(Subtitle), typeof(string),
typeof(MyCardView), string.Empty, propertyChanged: OnSubtitleChanged);
public string Subtitle
{
get => (string)GetValue(SubtitleProperty);
set => SetValue(SubtitleProperty, value);
}
private static void OnSubtitleChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (MyCardView)bindable;
control.SubtitleLabel.Text = (string)newValue;
}
}
<controls:MyCardView Title="Welcome" Subtitle="Powered by MAUI" />
โ This component is now reusable anywhere in your app.
Bindable properties allow your controls to support data binding. They are the foundation of MAUI/MVVM communication.
public static readonly BindableProperty ValueProperty =
BindableProperty.Create(nameof(Value), typeof(int),
typeof(MySlider), 0);
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
โ Add propertyChanged callback for advanced behavior.
ControlTemplates let you define a UI layout that multiple controls can share.
<ControlTemplate x:Key="CardTemplate">
<Frame BackgroundColor="LightYellow" Padding="20">
<ContentPresenter />
</Frame>
</ControlTemplate>
<ContentView ControlTemplate="{StaticResource CardTemplate}">
<Label Text="This is templated content" />
</ContentView>
โ Powerful for themeable and reusable structures.
DataTemplates define how each item in a collection is displayed.
<CollectionView ItemsSource="{Binding Products}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10">
<Label Text="{Binding Name}" />
<Label Text="{Binding Price}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
โ Ideal for lists, cards, grids, and custom layouts.
Handlers allow platform-specific customization of MAUI controls. They are the modern alternative to Xamarin.Forms renderers.
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("BorderColor", (handler, view) =>
{
#if ANDROID
handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.LightBlue);
#endif
});
โ Handlers are lightweight โ No inheritance needed โ Apply per control or globally
This example shows custom UI + bindable property.
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:Class="MyApp.Controls.RatingControl">
<HorizontalStackLayout x:Name="StarsLayout" />
</ContentView>
public partial class RatingControl : ContentView
{
public static readonly BindableProperty RatingProperty =
BindableProperty.Create(nameof(Rating), typeof(int),
typeof(RatingControl), 0, propertyChanged: OnRatingChanged);
public int Rating
{
get => (int)GetValue(RatingProperty);
set => SetValue(RatingProperty, value);
}
public RatingControl()
{
InitializeComponent();
BuildStars();
}
private static void OnRatingChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (RatingControl)bindable;
control.BuildStars();
}
private void BuildStars()
{
StarsLayout.Children.Clear();
for (int i = 1; i <= 5; i++)
{
string star = i <= Rating ? "โ
" : "โ";
StarsLayout.Children.Add(new Label { Text = star, FontSize = 30 });
}
}
}
<controls:RatingControl Rating="{Binding ProductRating}" />
โ Clean, reusable, MVVM-friendly component.
| MAUI-CommunityToolkit-9 :👈 | 👉:MAUI-CommunityToolkit-11 |