Upgrading from Xamarin.CommunityToolkit.Markup to CommunityToolkit.Maui.Markup

Upgrading from Xamarin.CommunityToolkit.Markup to CommunityToolkit.Maui.Markup

In Xamarin.Forms, we used Xamarin.CommunityToolkit.Markup to create our UI using C# (no XAML).

For .NET MAUI, we can continue to create our UIs in C# (No XAML) thanks to CommunityToolkit.Maui.Markup.

Let's take a look at the key differences between the two libraries, and then we'll learn how to get started!

Typed Bindings

The biggest update in CommunityToolkit.Maui is the introduction of Typed Bindings.

With Typed Bindings we can directly reference the property in our ViewModel, avoiding using reflection when INotifyPropertyChanged is called:

new Label()
  .Bind(Label.TextProperty,
        getter: (MyViewModel vm) => vm.LabelText,
        setter: (MyViewModel vm, string text) => vm.LabelText = text);

With Typed Bindings, we can also include a converter inline, eliminating the need to create a separate IValueConverter:

new Label()
  .Bind(Label.TextProperty,
        getter: (MyViewModel vm) => vm.LabelText,
        setter: (MyViewModel vm, string text) => vm.LabelText = text,
        convert: (string textFromViewModel) => textFromViewModel.Trim(),
        convertBack: (string textFromView) => textFromView.Trim());

Learn more about the Typed Bindings here: https://learn.microsoft.com/dotnet/communitytoolkit/maui/markup/extensions/bindable-object-extensions#bind

Relative Bindings

While Typed Bindings are great, they do not support Relative Bindings.

To leverage RelativeBindingSource, we continue to use the "old" binding engine:

new Label()
  .Bind(Label.TextProperty, 
        nameof(MyViewModel.LabelText), 
        source: new RelativeBindingSource(RelativeBindingSourceMode.FindAncestorBindingContext, typeof(MyViewModel))

Getting Started

Install CommunityToolkit.Maui.Markup

In your .NET MAUI csproj file, add the following package reference to CommunityToolkit.Maui.Markup:

<ItemGroup>
    <PackageReference Include="CommunityToolkit.Maui.Markup" Version="4.0.0"/>
</ItemGroup>

Install CommunityToolkit.MVVM

I highly recommend also installing the MVVM Community Toolkit. The MVVM Community Toolkit allows us to remove tons of MVVM boiler-plate code, replacing many lines of code with one attribute, like [ObservableProperty] and [RelayCommand].

You can see how I've used the MVVM Toolkit attributes in the sample code of my ViewModel down below.

In your .NET MAUI csproj file, add the following package reference to CommunityToolkit.Maui.Markup:

<ItemGroup>
    <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2"/>
</ItemGroup>

Learn more about the MVVM Community Toolkit here: https://learn.microsoft.com/dotnet/architecture/maui/mvvm-community-toolkit-features

Creating UI in C#

For this example, let's re-write MainPage.xaml that is included in the template when we create a File -> New .NET MAUI app using Visual Studio.

class MainPage : ContentPage
{
	public MainPage(MainViewModel vm)
	{
		BindingContext = vm;
        
		Content = new ScrollView
		{
			Content = new VerticalStackLayout
			{
				Spacing = 25,
				Padding = 30,

				Children =
				{
					new Label()
						.Text("Hello World")
						.Font(size: 32)
						.CenterHorizontal(),

					new Label()
						.Text("Welcome to .NET MAUI Markup Community Toolkit Sample")
						.Font(size: 18)
						.CenterHorizontal(),

					new Label()
						.Font(size: 18, bold: true)
						.CenterHorizontal()
						.Bind(Label.TextProperty,
								static (MainViewModel vm) => vm.ClickCount,
								convert: count => $"Current Count: {count}"),

					new Button()
						.Text("Click Me")
						.Font(bold: true)
						.CenterHorizontal()
						.Bind(Button.CommandProperty,
								static (MainViewModel vm) => vm.IncrementClickMeButtonCommand,
								mode: BindingMode.OneTime),

					new Image()
						.Source("dotnet_bot")
						.Size(250, 310)
						.CenterHorizontal()
				}
			}
		};
	}
}

partial class MainViewModel : ObservableObject
{
	[ObservableProperty]
	int _clickCount = 0;

	[RelayCommand]
	void IncrementClickMeButton() => ClickCount++;
}

You can find the completed open-source sample here: https://github.com/brminnick/HelloMauiMarkup

Resources

GitHub - CommunityToolkit/Maui.Markup: The .NET MAUI Markup Community Toolkit is a community-created library that contains Fluent C# Extension Methods to easily create your User Interface in C#
The .NET MAUI Markup Community Toolkit is a community-created library that contains Fluent C# Extension Methods to easily create your User Interface in C# - CommunityToolkit/Maui.Markup
GitHub - brminnick/HelloMauiMarkup: An iOS, Android, macOS + Windows app built using .NET MAUI, demonstrating how to use the .NET MAUI Markup Community Toolkit
An iOS, Android, macOS + Windows app built using .NET MAUI, demonstrating how to use the .NET MAUI Markup Community Toolkit - brminnick/HelloMauiMarkup