Skip to content

Conversation

@TheCodeTraveler
Copy link
Collaborator

@TheCodeTraveler TheCodeTraveler commented Jan 2, 2026

Description of Change

This PR implements [AttachedBindableProperty<T>("PropertyName")]:

The attribute can be applied to a Class, like so:

using CommunityToolkit.Maui;
using Microsoft.Maui.Controls;

namespace TestNamespace

[AttachedBindableProperty<string>("Text")]
public partial class TestClass : View
{
    // Alternatively, it can be placed on the constructor, for example:
    // [AttachedBindableProperty<string>("Text")]
    public TestClass()
    {
    }
}

Both usages will generate the following source code:

// <auto-generated>
// See: CommunityToolkit.Maui.SourceGenerators.Internal.AttachedBindablePropertyAttributeSourceGenerator
#pragma warning disable
#nullable enable
namespace TestNamespace;
public partial class TestClass
{
	/// <summary>
	/// Attached BindableProperty for the Text property.
	/// </summary>
	public static readonly global::Microsoft.Maui.Controls.BindableProperty TextProperty = global::Microsoft.Maui.Controls.BindableProperty.CreateAttached("Text", typeof(string), typeof(TestNamespace. TestClass), null, Microsoft.Maui.Controls.BindingMode.OneWay, null, null, null, null, null);
	/// <summary>
	/// Gets Text for the <paramref = "bindable"/> child element.
	/// </summary>
	public static string GetText(global::Microsoft.Maui.Controls.BindableObject bindable) => (string)bindable.GetValue(TextProperty);
	/// <summary>
	/// Sets Text for the <paramref = "bindable"/> child element.
	/// </summary>
	public static void SetText(global::Microsoft.Maui.Controls.BindableObject bindable, string value) => bindable.SetValue(TextProperty, value);
}

PR Checklist

  • Has a linked Issue, and the Issue has been approved(bug) or Championed (feature/proposal)
  • Has tests (if omitted, state reason in description)
  • Has samples (if omitted, state reason in description)
  • Rebased on top of main at time of PR
  • Changes adhere to coding standard

Additional information

This PR is still in draft as some unit tests are still failing and need to be resolved.

This PR unblocks #3016 and #3000

Copy link
Member

@pictos pictos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work, I've a couple of comments about it

static void ExecuteAllValues(SourceProductionContext context, ImmutableArray<AttachedBindablePropertySemanticValues> semanticValues)
{
// Pre-allocate dictionary with expected capacity
var groupedValues = new Dictionary<(string, string, string, string), List<AttachedBindablePropertySemanticValues>>(semanticValues.Length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say to create a record type for the key

var attachedBindablePropertiesCount = 0;
foreach (var value in values)
{
foreach (var abp in value.BindableProperties.AsImmutableArray())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the usage of AsImmutableArray?

{
var newBuffer = System.Buffers.ArrayPool<AttachedBindablePropertyModel>.Shared.Rent(attachedBindablePropertiesBuffer.Length * 2);
Array.Copy(attachedBindablePropertiesBuffer, newBuffer, attachedBindablePropertiesBuffer.Length);
System.Buffers.ArrayPool<AttachedBindablePropertyModel>.Shared.Return(attachedBindablePropertiesBuffer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't cleaning up the array when returning to the pool, this will make this array to hold values there, which can lead in bugs if we use the full Length of the array instead of the right number of BindableProperties

}
}

var attachedBindableProperties = ImmutableArray.Create(attachedBindablePropertiesBuffer, 0, attachedBindablePropertiesCount);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not create the EquatableArray directly? Here we're allocating an ImmutableArray just to use it to allocate an EquatableArray. I see the EquatableArray ctor only allows ImmutableArray, maybe we could add an overload that accepts an Array. Since it holds the collection as an Array anyway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants