14.0.0: Introducing Bindable Property Source Generators!
CommunityToolkit.Maui v14.0.0
I am excited to debut two new source generators!
[BindableProperty][AttachedBindableProperty<T>]
These new source generators make it easier than ever to create a BindableProperty for your .NET MAUI apps by allowing us to write all the associated boiler-plate code for you. In fact, all Bindable Properties in CommunityToolkit.Maui are now automatically generated using these new source generators!
For an in-depth overview of both [BindableProperty] and [AttachedBindableProperty<T>], check out my comprehensive write-up:
๐ https://codetraveler.io/2026/01/29/introducing-bindable-property-source-generators/
Bug Fixes + New Features
Alongside the new Source Generators, this Release also brings important bug fixes and new features:
StatusBarBehavior- Fixes
StatusBarBehavioron Android 35+
- Fixes
Snackbar- Fixes a memory leak
Popup- Add extension method for
NavigatedFromEventArgs - Fixes tapping issues when using a
CollectionViewinPopup - Fixes a memory leak
- Add extension method for
Introducing Bindable Property Source Generators
Opt-into this Experimental Feature
We have decided to release this feature using the [Experimental] attribute. This allows us to let you try out its features and provide feedback while giving us the flexibility to update it with your feedback over the next few releases.
In the csproj file of your .NET MAUI app, add the following code:
<!-- Opt into Bindable Property Source Generators -->
<PropertyGroup>
<NoWarn>MCTEXP001</NoWarn>
</PropertyGroup>
In the mean-time, we will be writing more comprehensive documentation and writing Analyzers, similar to CommunityToolkit.MVVM, to help provide you the best coding experience!
Using [BindableProperty]
To leverage the Bindable Property Source Generator, first ensure you using a partial class. Then, add the partial keyword and attach the [BindableProperty] attribute to your property:
- Add the
partialkeyword to the class - Add the
partialkeyword the Property for which to generate an associated Bindable Property - Add the
[BindableProperty]attribute to the property to make it bindable
using CommunityToolkit.Maui;
namespace BindablePropertySourceGeneratorSample;
public partial class CustomButton : Button
{
[BindableProperty]
public partial int? Number { get; set; }
}
The above example generates the following Bindable Property:
public partial class CustomButton
{
/// <summary>
/// BindableProperty for the <see cref = "Number"/> property.
/// </summary>
public static readonly global::Microsoft.Maui.Controls.BindableProperty NumberProperty = global::Microsoft.Maui.Controls.BindableProperty.Create("Number", typeof(int?), typeof(BindablePropertySourceGeneratorSample.CustomButton), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
public partial int? Number { get => (int)GetValue(NumberProperty); set => SetValue(NumberProperty, value); }
}
For more in-depth examples see my comprehensive write-up on [BindableProperty]:
๐ https://codetraveler.io/2026/01/29/introducing-bindable-property-source-generators/
Using [AttachedBindableProperty<T>]
Using [AttachedBindableProperty
.NET Multi-platform App UI (.NET MAUI) attached properties enable an object to assign a value for a property that its own class doesnโt define
To leverage the Attached Bindable Property Source Generator, first ensure you using a partial class. Then, add [AttachedBindableProperty<T>] attribute to either the class or constructor:
- Add the
partialkeyword to the class - Add the
[AttachedBindableProperty<T>]attribute to the class or constructor for which to generate an associated Attached Property
using CommunityToolkit.Maui;
namespace BindablePropertySourceGeneratorSample;
[AttachedBindableProperty<int>("Number")]
public partial class CustomButton : Button
{
public CustomButton()
{
}
}
Alternatively, the attribute can be attached to the constructor:
namespace BindablePropertySourceGeneratorSample;
public partial class CustomButton : Button
{
[CommunityToolkit.Maui.AttachedBindableProperty<int>("Number")]
public CustomButton()
{
}
}
Both examples above generate the following Attached Property along with its associated Get/Set methods:
public partial class CustomButton
{
/// <summary>
/// Attached BindableProperty for the Number property.
/// </summary>
public static readonly global::Microsoft.Maui.Controls.BindableProperty NumberProperty = global::Microsoft.Maui.Controls.BindableProperty.CreateAttached("Number", typeof(int), typeof(BindablePropertySourceGeneratorSample.CustomButton), null, (global::Microsoft.Maui.Controls.BindingMode)0, null, null, null, null, null);
/// <summary>
/// Gets Number for the <paramref name = "bindable"/> child element.
/// </summary>
public static int GetNumber(global::Microsoft.Maui.Controls.BindableObject bindable) => (int)bindable.GetValue(NumberProperty);
/// <summary>
/// Sets Number for the <paramref name = "bindable"/> child element.
/// </summary>
public static void SetNumber(global::Microsoft.Maui.Controls.BindableObject bindable, int value) => bindable.SetValue(NumberProperty, value);
}
For more in-depth examples see my comprehensive write-up on [AttachedBindableProperty<T>]:
๐ https://codetraveler.io/2026/01/29/introducing-bindable-property-source-generators/
Breaking Changes
FileSaver
We heard your feedback! You now have more control over which Permissions you require and when you request them.
Developers must now manually request Permissions.StorageRead and Permissions.StorageWrite:
var readPermissionsRequest = await Permissions.RequestAsync<Permissions.StorageRead>();
var writePermissionsRequest = await Permissions.RequestAsync<Permissions.StorageWrite>();
FolderPicker
We heard your feedback! You now have more control over which Permissions you require and when you request them.
Developers must now manually request Permissions.StorageRead and Permissions.StorageWrite:
var readPermissionsRequest = await Permissions.RequestAsync<Permissions.StorageRead>();
var writePermissionsRequest = await Permissions.RequestAsync<Permissions.StorageWrite>();
SpeechToText
We heard your feedback! You now have more control over which Permissions you require and when you request them.
Developers must now manually request permissions for Permissions.Microphone and manually call ISpeechToText.RequestPermissions():
static async Task<bool> ArePermissionsGranted(ISpeechToText speechToText, CancellationToken token = default)
{
var microphonePermissionStatus = await Permissions.RequestAsync<Permissions.Microphone>();
var isSpeechToTextRequestPermissionsGranted = await speechToText.RequestPermissions(token);
return microphonePermissionStatus is PermissionStatus.Granted
&& isSpeechToTextRequestPermissionsGranted;
}
Whatโs Changed
- Fix StatusBar on Android 35+ by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2939
- Fixes Obsolete Warnings and NuGet Package Dependency Warnings by Vladislav Antonyuk in https://github.com/CommunityToolkit/Maui/pull/2944
- Update ColorConversionExtensions.shared.cs by @stephenquan in https://github.com/CommunityToolkit/Maui/pull/2945
- Add popup related navigation extension methods by @jamesbrooksbank in https://github.com/CommunityToolkit/Maui/pull/2955
- [Housekeeping] Add
ReferenceAssembliesExtensionsextension forReferenceAssemblies.Net.Net100by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2956 - Update
[BindableProperty]Support for Additional Scenarios, AddCommunityToolkit.Maui.SourceGenerators.Internal.UnitTests, Implement[BindableProperty]for Behaviors by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2932 - Add
CommunityToolkit.Maui.SourceGenerator.Benchmarks, Reduce Memory Allocations on[BindableProperty]Source Generator by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2960 - Use
[BindableProperty]for RatingView by Clifford Agius in https://github.com/CommunityToolkit/Maui/pull/2964 - Cleanup Popup Resources When Closed by @AlejoTorresLeon in https://github.com/CommunityToolkit/Maui/pull/2971
- Add
[Experimental]To[BindableProperty]by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2990 - Extend BindableProperty source gen to handle partial property initializers by @stephenquan in https://github.com/CommunityToolkit/Maui/pull/2987
- Add BoxView behind the Popup content to safely handle touch interaction by Shaun Lawrence in https://github.com/CommunityToolkit/Maui/pull/2997
- Bindable property for Popup by James Crutchley in https://github.com/CommunityToolkit/Maui/pull/2991
- Remove
BindablePropertyAttribute.DefaultValueby Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/2995 - Refactor
Animationsto use [BindableProperty] partial properties by James Crutchley in https://github.com/CommunityToolkit/Maui/pull/3013 - Refactor Views to use
[BindableProperties]partial properties by James Crutchley in https://github.com/CommunityToolkit/Maui/pull/3017 - Implement
[BindableProperty]for Converters by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3018 - Implement
[BindableProperty]forImageSources, Add[BindableProperty]Support forinternalProperties by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3019 - Use
Copyinstead ofMovein FileSaver UI on iOS by Matt Goldman in https://github.com/CommunityToolkit/Maui/pull/2981 - Support null values in NumericValidationBehavior by @reck1610 in https://github.com/CommunityToolkit/Maui/pull/2886
- Refactor Layouts to use [BindableProperty] partial properties by James Crutchley in https://github.com/CommunityToolkit/Maui/pull/3016
- Implement
[BindableProperty]for ValidationBehaviors by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3000 - Remove
ReferenceAssembliesExtensionsby Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3038 - Create
[AttachedBindableProperty<T>]by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3024 - Fix memory leak on snackbar by Pedro Jesus in https://github.com/CommunityToolkit/Maui/pull/3034
- Fix Windows Picker Initial Path is not set by Vladislav Antonyuk in https://github.com/CommunityToolkit/Maui/pull/3030
- Fix clicking on notification does not restore activity by James Crutchley in https://github.com/CommunityToolkit/Maui/pull/2979
- Prepare
[AttachedBindableProperty<T>]and[BindableProperty]for Release by Brandon Minnick in https://github.com/CommunityToolkit/Maui/pull/3047 - Fix memory leak by changing now playing artwork request handler by @MarcelStommel in https://github.com/CommunityToolkit/Maui/pull/3051
New Contributors
- @jamesbrooksbank made their first contribution in https://github.com/CommunityToolkit/Maui/pull/2955
- @AlejoTorresLeon made their first contribution in https://github.com/CommunityToolkit/Maui/pull/2971
- Matt Goldman made their first contribution in https://github.com/CommunityToolkit/Maui/pull/2981
- @reck1610 made their first contribution in https://github.com/CommunityToolkit/Maui/pull/2886
- @MarcelStommel made their first contribution in https://github.com/CommunityToolkit/Maui/pull/3051
Full Changelog: https://github.com/CommunityToolkit/Maui/compare/13.0.0โฆ14.0.0