ronantakizawa/codereview-bench huggingface dataset:
Repository: dotnet/maui
File: src/Core/maps/src/Platform/iOS/MauiMKMapView.cs (C#)

Code before:
﻿using System;
using System.Collections;
using System.Linq;
using CoreLocation;
using MapKit;
using Microsoft.Maui.Maps.Handlers;
using Microsoft.Maui.Platform;
using ObjCRuntime;
using UIKit;

namespace Microsoft.Maui.Maps.Platform
{
	public class MauiMKMapView : MKMapView
	{
		WeakReference<IMapHandler> _handlerRef;
		object? _lastTouchedView;
		UITapGestureRecognizer? _mapClickedGestureRecognizer;

		public MauiMKMapView(IMapHandler handler)
		{
			_handlerRef = new WeakReference<IMapHandler>(handler);
			OverlayRenderer = GetViewForOverlayDelegate;
			base.GetViewForAnnotation = GetViewForAnnotation;
		}

		internal IMapHandler? Handler
		{
			get
			{
				_handlerRef.TryGetTarget(out var handler);
				return handler;
			}
			set
			{
				if (value is not null)
				{
					_handlerRef = new WeakReference<IMapHandler>(value);
				}
			}
		}

		public override void MovedToWindow()
		{
			base.MovedToWindow();
			if (Window != null)
				Startup();
			else
				Cleanup();
		}

Review comment (suggestion):
Can include a comment?

```
// Assign custom annotation view delegate to enable gesture recognition on annotation callouts.
```

Code after:
﻿using System;
using System.Collections;
using System.Linq;
using CoreLocation;
using MapKit;
using Microsoft.Maui.Maps.Handlers;
using Microsoft.Maui.Platform;
using ObjCRuntime;
using UIKit;

namespace Microsoft.Maui.Maps.Platform
{
	public class MauiMKMapView : MKMapView
	{
		WeakReference<IMapHandler> _handlerRef;
		object? _lastTouchedView;
		UITapGestureRecognizer? _mapClickedGestureRecognizer;

		public MauiMKMapView(IMapHandler handler)
		{
			_handlerRef = new WeakReference<IMapHandler>(handler);
			OverlayRenderer = GetViewForOverlayDelegate;
			// Assign custom annotation view delegate to enable gesture recognition on annotation callouts.
			base.GetViewForAnnotation = GetViewForAnnotation;
		}

		internal IMapHandler? Handler
		{
			get
			{
				_handlerRef.TryGetTarget(out var handler);
				return handler;
			}
			set
			{
				if (value is not null)
				{
					_handlerRef = new WeakReference<IMapHandler>(value);
				}
			}
		}

		public override void MovedToWindow()
		{
			base.MovedToWindow();
			if (Window != null)
				Startup();
			else
				Cleanup();
Repository: dotnet/maui
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13123.cs (C#)

Code before:
        [Category(UITestCategories.Maps)]
        public void InfoWindowClickedEventShouldFire()
        {
            App.WaitForElement("Map");
            TapMapPin();
            App.WaitForElement("Marker Clicked: Yes");
            TapInfoWindow();
            App.WaitForElement("Test Result: PASSED");
        }

        private void TapMapPin()
        {
            var mapElement = App.FindElement("Map");
            var rect = mapElement.GetRect();
            var centerX = rect.X + rect.Width / 2;
            var centerY = rect.Y + rect.Height / 2;
            App.TapCoordinates(centerX, centerY);
        }

        private void TapInfoWindow()
        {
            var mapElement = App.FindElement("Map");
            var rect = mapElement.GetRect();
#if IOS
            var centerX = rect.X + rect.Width / 2;
            var infoWindowY = rect.Y + rect.Height / 2 - 30;
             App.TapCoordinates(centerX, infoWindowY);
#elif MACCATALYST
            var centerX = rect.X + rect.Width / 2 + 20;
            var infoWindowY = rect.Y + rect.Height / 2;
            App.TapCoordinates(centerX, infoWindowY);
#endif
        }

    }
}
#endif


Review comment (suggestion):
Could improve that "magic numbers" creating some constants, like `const int InfoWindowOffsetFromCenter = 30;`
But is in the sample, is fine.

Code after:

        [Test]
        [Category(UITestCategories.Maps)]
        public void InfoWindowClickedEventShouldFire()
        {
            App.WaitForElement("Map");
            TapMapPin();
            App.WaitForElement("Marker Clicked: Yes");
            TapInfoWindow();
            App.WaitForElement("Test Result: PASSED");
        }

        private void TapMapPin()
        {
            var mapElement = App.FindElement("Map");
            var rect = mapElement.GetRect();
            var centerX = rect.X + rect.Width / 2;
            var centerY = rect.Y + rect.Height / 2;
            App.TapCoordinates(centerX, centerY);
        }

        private void TapInfoWindow()
        {
            var mapElement = App.FindElement("Map");
            var rect = mapElement.GetRect();
#if IOS
            var centerX = rect.X + rect.Width / 2;
            var infoWindowY = rect.Y + rect.Height / 2 - InfoWindowOffsetFromCenter;
            App.TapCoordinates(centerX, infoWindowY);
#elif MACCATALYST
            var centerX = rect.X + rect.Width / 2 + 20;
            var infoWindowY = rect.Y + rect.Height / 2;
            App.TapCoordinates(centerX, infoWindowY);
#endif
        }

    }
}
#endif
Repository: dotnet/maui
File: src/Controls/src/Core/Handlers/Items2/iOS/CarouselViewController2.cs (C#)

Code before:
			if (CollectionView is null || ItemsSource?.ItemCount == 0)
			{
				return;
			}
			//Get current visible item index paths to ensure proper refresh of carousel items
			var indexPaths = CollectionView.IndexPathsForVisibleItems;
			if (indexPaths?.Length > 0)
			{
				CollectionView.ReloadItems(indexPaths);
			}
		}

		private protected override void DetachingFromWindow()
		{
			_wasDetachedFromWindow = true;
			base.DetachingFromWindow();
			TearDown(ItemsView);
		}

		internal bool InitialPositionSet { get; private set; }

		void TearDown(CarouselView carouselView)
		{
			_oldViews = null;
			InitialPositionSet = false;

			UnsubscribeCollectionItemsSourceChanged(ItemsSource);

			_carouselViewLoopManager?.Dispose();
			_carouselViewLoopManager = null;
			_isUpdating = false;
		}

		void Setup(CarouselView carouselView)
		{
			InitializeCarouselViewLoopManager();

			_oldViews = new List<View>();

			SubscribeCollectionItemsSourceChanged(ItemsSource);
		}

		internal void UpdateIsScrolling(bool isScrolling)
		{
			if (ItemsView is CarouselView carousel)
			{
				carousel.IsScrolling = isScrolling;
			}
		}

		internal NSIndexPath GetScrollToIndexPath(int position)

Review comment (suggestion):
Low probabilities, but if `ItemsSource` is swapped while in the middle of `RefreshVisibleItems()`, it could produce inconsistent results. A defensive copy of indexPaths or re-check inside the loop would make it safer.

Code after:
			=> (typeof(CarouselTemplatedCell2), CarouselTemplatedCell2.ReuseId);

		protected override Items.IItemsViewSource CreateItemsViewSource()
		{
			var itemsSource = ItemsSourceFactory2.CreateForCarouselView(ItemsView.ItemsSource, this, ItemsView.Loop);
			_carouselViewLoopManager?.SetItemsSource(itemsSource);
			SubscribeCollectionItemsSourceChanged(itemsSource);
			return itemsSource;
		}

		private protected override async void AttachingToWindow()
		{
			base.AttachingToWindow();
			Setup(ItemsView);
			// Refresh the current visible items after setup to catch any ItemsSource changes that occurred on other pages
			// This ensures that updates made on other pages are reflected when navigating back
			if (_wasDetachedFromWindow)
			{
				RefreshVisibleItems();
			}
			_wasDetachedFromWindow = false;
			// if we navigate back on NavigationController LayoutSubviews might not fire.
			await UpdateInitialPosition();
		}

		void RefreshVisibleItems()
		{
			if (CollectionView is null || ItemsSource?.ItemCount == 0)
			{
				return;
			}

			// Get current visible item index paths to ensure proper refresh of carousel items
			var indexPaths = CollectionView.IndexPathsForVisibleItems;
			if (indexPaths?.Length > 0)
			{
				CollectionView.ReloadItems(indexPaths);
			}
		}

		private protected override void DetachingFromWindow()
		{
			_wasDetachedFromWindow = true;
			base.DetachingFromWindow();
			TearDown(ItemsView);
		}

		internal bool InitialPositionSet { get; private set; }

		void TearDown(CarouselView carouselView)
		{
Repository: dotnet/maui
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30575.cs (C#)

Code before:
﻿using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue30575 : _IssuesUITest
{
	public Issue30575(TestDevice device) : base(device) { }

	public override string Issue => "FlowDirection RightToLeft causes mirrored content in WebView";

	[Test]
	[Category(UITestCategories.WebView)]
	public void WebViewShouldNotMirrored()
	{
		VerifyInternetConnectivity();
		App.WaitForElement("WebViewLabel");
		Thread.Sleep(3000);
		VerifyScreenshot();
	}
}

Review comment (bug):
```
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: WebViewShouldNotMirrored.png (1.90% difference)
```
<img width="1080" height="1735" alt="image" src="https://github.com/user-attachments/assets/5a6df664-6ece-40e9-906c-8b8e763738d0" />

Failing on Android, Mac and Windows.

Code after:
﻿using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue30575 : _IssuesUITest
{
	public Issue30575(TestDevice device) : base(device) { }

	public override string Issue => "FlowDirection RightToLeft causes mirrored content in WebView";

	[Test]
	[Category(UITestCategories.WebView)]
	public void WebViewShouldNotMirrored()
	{
		App.WaitForElement("WebViewLabel");
		Thread.Sleep(3000);
		VerifyScreenshot();
	}
}
Repository: dotnet/maui
File: src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs (C#)

Code before:
		}

		void TearDownEmptyView()
		{
			HideEmptyView();

			// RemoveLogicalChild will trigger a disposal of the native view and its content
			ItemsView.RemoveLogicalChild(_emptyViewFormsElement);

			_emptyUIView = null;
			_emptyViewFormsElement = null;
		}

		virtual internal CGRect LayoutEmptyView()
		{
			if (!_initialized || _emptyUIView == null || _emptyUIView.Superview == null)
			{
				return CGRect.Empty;
			}

			var frame = DetermineEmptyViewFrame();

			if (_emptyViewFormsElement != null && ((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) != -1)
			{
				_emptyViewFormsElement.Measure(frame.Width, frame.Height);
				_emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height));
			}

			_emptyUIView.Frame = frame;

			return frame;
		}

		internal protected virtual void UpdateVisibility()
		{
			if (ItemsView.IsVisible)
			{
				if (CollectionView.Hidden)
				{
					CollectionView.ReloadData();
					CollectionView.Hidden = false;
					Layout.InvalidateLayout();
					CollectionView.LayoutIfNeeded();
				}
			}
			else
			{
				CollectionView.Hidden = true;
			}
		}


Review comment (suggestion):
Could include a comment here?

```
// Arrange in the native container's local coordinate space (0,0).
// The native container (_emptyUIView) is already positioned correctly by iOS,
// so the MAUI element just needs to fill its container without additional offset.
```

Code after:
			}

			_emptyUIView.RemoveFromSuperview();

			_emptyViewDisplayed = false;
		}

		void TearDownEmptyView()
		{
			HideEmptyView();

			// RemoveLogicalChild will trigger a disposal of the native view and its content
			ItemsView.RemoveLogicalChild(_emptyViewFormsElement);

			_emptyUIView = null;
			_emptyViewFormsElement = null;
		}

		virtual internal CGRect LayoutEmptyView()
		{
			if (!_initialized || _emptyUIView == null || _emptyUIView.Superview == null)
			{
				return CGRect.Empty;
			}

			var frame = DetermineEmptyViewFrame();

			if (_emptyViewFormsElement != null && ((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) != -1)
			{
				if (frame.Width > 0 && frame.Height > 0)
				{
					_emptyViewFormsElement.Measure(frame.Width, frame.Height);

					// Arrange in the native container's local coordinate space (0,0).
					// The native container (_emptyUIView) is already positioned correctly by iOS,
					// so the MAUI element just needs to fill its container without additional offset.
					_emptyViewFormsElement.Arrange(new Rect(0, 0, frame.Width, frame.Height));
				}
			}

			_emptyUIView.Frame = frame;

			return frame;
		}

		internal protected virtual void UpdateVisibility()
		{
			if (ItemsView.IsVisible)
			{
				if (CollectionView.Hidden)
				{
Repository: dotnet/maui
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24468.cs (C#)

Code before:
#if ANDROID || IOS //The test fails on Windows and MacCatalyst because the SetOrientation method, which is intended to change the device orientation, is only supported on mobile platforms iOS and Android.
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;
public class Issue24468 : _IssuesUITest
{
    public Issue24468(TestDevice device) : base(device)
    {
    }

    public override string Issue => "FlyoutPage toolbar button not updating on orientation change on Android";
    [Test]
    [Category(UITestCategories.Navigation)]
    public void FlyoutPageToolbarButtonUpdatesOnOrientationChange()
    {
        App.WaitForElement("ContentPage");

        App.SetOrientationLandscape();

        var text = App.FindElement("StatusLabel").GetText();
        Assert.That(text, Contains.Substring("ShouldShowToolbarButton is called"));
        App.SetOrientationPortrait();
    }
}
#endif


Review comment (suggestion):
Can use `try-finally` to always restore the state even if there is any error.

Code after:
#if ANDROID || IOS //The test fails on Windows and MacCatalyst because the SetOrientation method, which is intended to change the device orientation, is only supported on mobile platforms iOS and Android.
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;
public class Issue24468 : _IssuesUITest
{
    public Issue24468(TestDevice device) : base(device)
    {
    }

    public override string Issue => "FlyoutPage toolbar button not updating on orientation change on Android and Windows";
    [Test]
    [Category(UITestCategories.Navigation)]
    public void FlyoutPageToolbarButtonUpdatesOnOrientationChange()
    {
        App.SetOrientationLandscape();
        App.WaitForElement("ContentPage");

        try
        {
            App.WaitForElement("EventLabel");
            var eventText = App.FindElement("EventLabel").GetText();
            Assert.That(eventText, Is.EqualTo("ShouldShowToolbarButton called"));
            
            var callCount = int.Parse(App.FindElement("CountLabel").GetText() ?? "0");
            Assert.That(callCount, Is.GreaterThan(1).And.LessThan(5), 
                $"Expected call count between 2-4, but got {callCount}. Method should not be called excessively.");
        }
        finally
        {
            App.SetOrientationPortrait();
        }
    }
}
#endif
Repository: dotnet/maui
File: src/Core/src/Platform/Android/MauiWebViewClient.cs (C#)

Code before:
			}

			base.OnReceivedError(view, request, error);
		}

		// The render process was observed to crash or killed by the system.
		[System.Runtime.Versioning.SupportedOSPlatform("android26.0")]
		public override bool OnRenderProcessGone(WebView? view, RenderProcessGoneDetail? detail)
		{
			if (_handler.TryGetTarget(out var handler))
			{
				handler.VirtualView.ProcessTerminated(new WebProcessTerminatedEventArgs(view, detail));
			}

			return base.OnRenderProcessGone(view, detail);
		}

		bool NavigatingCanceled(string? url) =>
			!_handler.TryGetTarget(out var handler) || handler.NavigatingCanceled(url);

		static bool IsBlankNavigation(string? url)
		{
			if (string.IsNullOrWhiteSpace(url))
				return false;

			// Check if URL is about:blank (case insensitive)
			return string.Equals(url.Trim(), "about:blank", StringComparison.OrdinalIgnoreCase);
		}

		static string GetValidUrl(string? url)
		{
			if (string.IsNullOrEmpty(url))
				return string.Empty;

			return url;
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
				Disconnect();

			base.Dispose(disposing);
		}

		internal void Disconnect()
		{
			_handler.SetTarget(null);
		}
	}
}

Review comment (suggestion):
`if (navigate && !IsBlankNavigation(url))`

Based on this:
- url = null → IsBlankNavigation returns false → Navigated fires 
- url = "about:blank" → IsBlankNavigation returns true → Navigated doesn't fire

This could break the fix from #29234 which wanted to prevent events when Source is null

Code after:
					_navigationResult = WebNavigationResult.Timeout;
			}

			base.OnReceivedError(view, request, error);
		}

		// The render process was observed to crash or killed by the system.
		[System.Runtime.Versioning.SupportedOSPlatform("android26.0")]
		public override bool OnRenderProcessGone(WebView? view, RenderProcessGoneDetail? detail)
		{
			if (_handler.TryGetTarget(out var handler))
			{
				handler.VirtualView.ProcessTerminated(new WebProcessTerminatedEventArgs(view, detail));
			}

			return base.OnRenderProcessGone(view, detail);
		}

		bool NavigatingCanceled(string? url) =>
			!_handler.TryGetTarget(out var handler) || handler.NavigatingCanceled(url);

		static bool IsBlankNavigation(string? url)
		{
			// Null/empty URLs are handled by the early return in OnPageFinished,
			// so we only need to check for the explicit "about:blank" URL
			if (string.IsNullOrWhiteSpace(url))
				return false;

			// Check if URL is about:blank (case insensitive)
			return string.Equals(url.Trim(), "about:blank", StringComparison.OrdinalIgnoreCase);
		}

		static string GetValidUrl(string? url)
		{
			if (string.IsNullOrEmpty(url))
				return string.Empty;

			return url;
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
				Disconnect();

			base.Dispose(disposing);
		}

		internal void Disconnect()
		{
			_handler.SetTarget(null);
Repository: dotnet/maui
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32223.cs (C#)

Code before:
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue32223 : _IssuesUITest
{
	public Issue32223(TestDevice testDevice) : base(testDevice)
	{
	}
	public override string Issue => "[Android] CollectionView items do not reorder correctly when using an item DataTemplateSelector";

	[Test]
	[Category(UITestCategories.CollectionView)]
	public void CanReorderWithItemDataTemplateSelector()
	{
		App.WaitForElement("ReorderableCollectionView");
		App.DragAndDrop("David", "Charlie");
		VerifyScreenshot();
	}
}

Review comment (bug):
Add another test to drag “Charlie” above “Alice” and then back below “Bob” to verify reordering works bi-directionally across both templates and across more than one position, which catches off-by-one swaps.

Code after:
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue32223 : _IssuesUITest
{
	public Issue32223(TestDevice testDevice) : base(testDevice)
	{
	}
	public override string Issue => "[Android] CollectionView items do not reorder correctly when using an item DataTemplateSelector";

	[Test]
	[Category(UITestCategories.CollectionView)]
	public void CanReorderWithItemDataTemplateSelector()
	{
		App.WaitForElement("ReorderableCollectionView");
		App.DragAndDrop("David", "Charlie");
		var expectedText = App.WaitForElement("ReorderedLabel").GetText();
		Assert.That(expectedText, Is.EqualTo("Success"));
	}
}
Repository: dotnet/maui
File: src/Controls/tests/BindingSourceGen.UnitTests/SelfBindingTests.cs (C#)

Code before:
namespace BindingSourceGen.UnitTests;

public class SelfBindingTests
{
    [Fact]
    public void GenerateSelfBinding()
    {
        var source = """
        using Microsoft.Maui.Controls;
        var label = new Label();
        label.SetBinding(Label.TextProperty, static (string s) => s);
        """;

        var result = SourceGenHelpers.Run(source);
        
        // Should have no diagnostics
        AssertExtensions.AssertNoDiagnostics(result);
        
        // Should have generated a binding
        Assert.NotNull(result.Binding);
        
        // Check all generated files
        foreach (var file in result.GeneratedFiles)
        {
            Console.WriteLine($"\n=== File: {file.Key} ===");
            Console.WriteLine(file.Value);
        }
    }
}


Review comment (bug):
@copilot I don't want any leftover debugging writelines in the final code. Should there be an assert here instead?

Code after:
using Microsoft.Maui.Controls.BindingSourceGen;
using Xunit;
using System.Linq;

namespace BindingSourceGen.UnitTests;

public class SelfBindingTests
{
    [Fact]
    public void GenerateSelfBinding()
    {
        var source = """
        using Microsoft.Maui.Controls;
        var label = new Label();
        label.SetBinding(Label.TextProperty, static (string s) => s);
        """;

        var result = SourceGenHelpers.Run(source);
        
        // Should have no diagnostics
        AssertExtensions.AssertNoDiagnostics(result);
        
        // Should have generated a binding
        Assert.NotNull(result.Binding);
    }
}
Repository: dotnet/maui
File: src/Controls/tests/SourceGen.UnitTests/InitializeComponent/CompiledBindings.cs (C#)

Code before:
		foreach (var (expectedLine, actualLine) in expectedLines.Zip(actualLines))
		{
			Assert.Equal(expectedLine, actualLine);
		}

		Assert.Equal(expectedLines.Count(), actualLines.Count());

		static IEnumerable<string> SplitCode(string code)
			=> code.Split(Environment.NewLine)
				.Select(static line => line.Trim())
				.Where(static line => !string.IsNullOrWhiteSpace(line));
	}

	[Fact]
	public void CanCompileSelfBinding()
{
var xaml =
"""
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:test="clr-namespace:Test"
x:Class="Test.TestPage"
x:DataType="test:TestViewModel">
<Label Text="{Binding .}"/>
</ContentPage>
""";

var code =
"""
#nullable enable
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Test;

[XamlProcessing(XamlInflator.SourceGen)]
public partial class TestPage : ContentPage
{
public TestPage()
{
InitializeComponent();
}
}

public class TestViewModel
{
public override string ToString() => "ViewModel Value";
}

Review comment (suggestion):
@copilot this is a great test. Let's also add one for the `{Binding}` case -- there's no Path, not even the `.` character. I believe we could make this test a `[Theory]` with two values of the path.

Code after:
		foreach (var (expectedLine, actualLine) in expectedLines.Zip(actualLines))
		{
			Assert.Equal(expectedLine, actualLine);
		}

		Assert.Equal(expectedLines.Count(), actualLines.Count());

		static IEnumerable<string> SplitCode(string code)
			=> code.Split(Environment.NewLine)
				.Select(static line => line.Trim())
				.Where(static line => !string.IsNullOrWhiteSpace(line));
	}

	[Fact]
	public void CorrectlyDetectsNullableReferenceTypes()
	{
		var xaml =
"""
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	xmlns:test="clr-namespace:Test"
	x:Class="Test.TestPage"
	x:DataType="test:TestPage">
	<Entry Text="{Binding Product.Name}"/>
</ContentPage>
""";

		var code =
"""
#nullable enable
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Test;

[XamlProcessing(XamlInflator.SourceGen)]
public partial class TestPage : ContentPage
{
	public Product? Product { get; set; } = null;

	public TestPage()
	{
		InitializeComponent();
	}
}

public class Product
{