diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index 613b8c80f68e..2cc2aaf7d2fc 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -42,6 +42,7 @@ body:
label: Version with bug
description: In what version do you see this issue? Run `dotnet workload list` to find your version.
options:
+ - 10.0.0-rc.2
- 10.0.0-rc.1
- 10.0.0-preview.7
- 10.0.0-preview.6
@@ -50,6 +51,8 @@ body:
- 10.0.0-preview.3
- 10.0.0-preview.2
- 10.0.0-preview.1
+ - 9.0.110 SR12
+ - 9.0.111 SR11.1
- 9.0.110 SR11
- 9.0.100 SR10
- 9.0.90 SR9
@@ -133,6 +136,8 @@ body:
- 9.0.90 SR9
- 9.0.100 SR10
- 9.0.110 SR11
+ - 9.0.111 SR11.1
+ - 9.0.120 SR12
- 10.0.0-preview.1
- 10.0.0-preview.2
- 10.0.0-preview.3
@@ -141,6 +146,7 @@ body:
- 10.0.0-preview.6
- 10.0.0-preview.7
- 10.0.0-rc.1
+ - 10.0.0-rc.2
validations:
required: true
- type: dropdown
diff --git a/README.md b/README.md
index 70386a702084..a2bc3011705b 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,8 @@
* [.NET MAUI Samples](https://github.com/dotnet/maui-samples)
* [Development Guide](./.github/DEVELOPMENT.md)
+Create a new app with `dotnet new maui -n NewApp` or a [sample app](https://github.com/dotnet/maui-samples/tree/main/10.0/Apps/DeveloperBalance#developer-balance) with `dotnet new maui -n NewApp -sc` that includes the [open-source Syncfusion Toolkit for .NET MAUI](https://www.syncfusion.com/net-maui-toolkit?utm_source=msftdotnet&utm_medium=banner&utm_campaign=mauipremium_sep25) with over 30 additional controls, the [.NET MAUI Community Toolkit](https://github.com/CommunityToolkit/Maui) with tons of helpers and views, and [MVVM Toolkit](https://github.com/CommunityToolkit/dotnet).
+
## Overview
.NET Multi-platform App UI (.NET MAUI) is the evolution of Xamarin.Forms that expand capabilities beyond mobile Android and iOS into desktop apps for Windows and macOS. With .NET MAUI, you can build apps that perform great on any device that runs Windows, macOS, Android, & iOS from a single codebase. Coupled with Visual Studio productivity tools and emulators, .NET and Visual Studio significantly speed up the development process for building apps that target the widest possible set of devices. Use a single development stack that supports the best-of-breed solutions for all modern workloads with a unified SDK, base class libraries, and a toolchain. [Read More](https://docs.microsoft.com/dotnet/maui/what-is-maui)
diff --git a/coverage.runsettings b/coverage.runsettings
new file mode 100644
index 000000000000..135d318b972b
--- /dev/null
+++ b/coverage.runsettings
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eng/common/core-templates/job/source-build.yml b/eng/common/core-templates/job/source-build.yml
index d805d5faeb94..947f0971eb5c 100644
--- a/eng/common/core-templates/job/source-build.yml
+++ b/eng/common/core-templates/job/source-build.yml
@@ -34,6 +34,9 @@ parameters:
# container and pool.
platform: {}
+ # Optional list of directories to ignore for component governance scans.
+ componentGovernanceIgnoreDirectories: []
+
is1ESPipeline: ''
# If set to true and running on a non-public project,
@@ -94,3 +97,4 @@ jobs:
parameters:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
platform: ${{ parameters.platform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
diff --git a/eng/common/core-templates/jobs/source-build.yml b/eng/common/core-templates/jobs/source-build.yml
index d92860cba208..eb4b923a7777 100644
--- a/eng/common/core-templates/jobs/source-build.yml
+++ b/eng/common/core-templates/jobs/source-build.yml
@@ -15,6 +15,9 @@ parameters:
# one job runs on 'defaultManagedPlatform'.
platforms: []
+ # Optional list of directories to ignore for component governance scans.
+ componentGovernanceIgnoreDirectories: []
+
is1ESPipeline: ''
# If set to true and running on a non-public project,
@@ -31,6 +34,7 @@ jobs:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
jobNamePrefix: ${{ parameters.jobNamePrefix }}
platform: ${{ platform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
enableInternalSources: ${{ parameters.enableInternalSources }}
- ${{ if eq(length(parameters.platforms), 0) }}:
@@ -39,4 +43,5 @@ jobs:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
jobNamePrefix: ${{ parameters.jobNamePrefix }}
platform: ${{ parameters.defaultManagedPlatform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
enableInternalSources: ${{ parameters.enableInternalSources }}
diff --git a/eng/common/core-templates/steps/get-delegation-sas.yml b/eng/common/core-templates/steps/get-delegation-sas.yml
index d2901470a7f0..c6cbea4e8d59 100644
--- a/eng/common/core-templates/steps/get-delegation-sas.yml
+++ b/eng/common/core-templates/steps/get-delegation-sas.yml
@@ -26,6 +26,7 @@ steps:
inputs:
azureSubscription: ${{ parameters.federatedServiceConnection }}
scriptType: 'pscore'
+ addSpnToEnvironment: true
scriptLocation: 'inlineScript'
inlineScript: |
# Calculate the expiration of the SAS token and convert to UTC
diff --git a/eng/common/core-templates/steps/get-federated-access-token.yml b/eng/common/core-templates/steps/get-federated-access-token.yml
index 3a4d4410c482..cff1236fc8d5 100644
--- a/eng/common/core-templates/steps/get-federated-access-token.yml
+++ b/eng/common/core-templates/steps/get-federated-access-token.yml
@@ -31,6 +31,7 @@ steps:
inputs:
azureSubscription: ${{ parameters.federatedServiceConnection }}
scriptType: 'pscore'
+ addSpnToEnvironment: true
scriptLocation: 'inlineScript'
inlineScript: |
$accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv
diff --git a/eng/pipelines/arcade/setup-test-env.yml b/eng/pipelines/arcade/setup-test-env.yml
index 655ca1cf7b15..9393f6f4c812 100644
--- a/eng/pipelines/arcade/setup-test-env.yml
+++ b/eng/pipelines/arcade/setup-test-env.yml
@@ -28,7 +28,11 @@ steps:
xcrun xcode-select --print-path
xcodebuild -version
sudo xcodebuild -license accept
- sudo xcodebuild -downloadPlatform iOS
+ if [[ ${XCODE_VERSION/\.*/} -ge 26 ]]; then
+ sudo xcodebuild -downloadPlatform iOS -architectureVariant universal
+ else
+ sudo xcodebuild -downloadPlatform iOS
+ fi
sudo xcodebuild -runFirstLaunch
displayName: Select Xcode Version
condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'))
diff --git a/eng/pipelines/maui-release-internal.yml b/eng/pipelines/maui-release-internal.yml
index 06e49fb4b69c..0e4d2d3fd9ce 100644
--- a/eng/pipelines/maui-release-internal.yml
+++ b/eng/pipelines/maui-release-internal.yml
@@ -74,6 +74,8 @@ extends:
${{ else }}:
template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates
parameters:
+ settings:
+ networkIsolationPolicy: Permissive
pool: ${{ parameters.VM_IMAGE_HOST }}
sdl:
binskim:
diff --git a/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs
index 15330f14b416..6c25104d3961 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs
@@ -124,6 +124,11 @@ public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
Page.SendAppearing();
+ if (!_intialLayoutFinished)
+ {
+ _intialLayoutFinished = true;
+ SetInitialPresented();
+ }
}
public override void ViewDidDisappear(bool animated)
@@ -158,19 +163,6 @@ void SetInitialPresented()
UpdateLeftBarButton();
}
- public override void ViewWillLayoutSubviews()
- {
- // Orientation doesn't seem to be set to a stable correct value until here.
- // So, we officially process orientation here.
- if (!_intialLayoutFinished)
- {
- _intialLayoutFinished = true;
- SetInitialPresented();
- }
-
- base.ViewWillLayoutSubviews();
- }
-
public override void ViewDidLoad()
{
base.ViewDidLoad();
diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
index a99761006d73..b9395408034d 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs
@@ -2089,7 +2089,13 @@ class Container : UIView
public Container(View view, UINavigationBar bar) : base(bar.Bounds)
{
- if (OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11))
+ // For iOS 26+, we need to use autoresizing masks instead of constraints to ensure proper TitleView display
+ if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))
+ {
+ TranslatesAutoresizingMaskIntoConstraints = true;
+ AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
+ }
+ else if (OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11))
{
TranslatesAutoresizingMaskIntoConstraints = false;
}
@@ -2178,7 +2184,9 @@ public override CGRect Frame
{
if (Superview != null)
{
- if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11)))
+ // For iOS 26+ and pre-iOS 11, we use autoresizing masks and need to adjust the frame manually
+ if (OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26) ||
+ !(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11)))
{
value.Y = Superview.Bounds.Y;
diff --git a/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs b/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs
index e3315ac88ed8..09b8636591c6 100644
--- a/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs
+++ b/src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs
@@ -18,6 +18,10 @@ public partial class StructuredItemsViewHandler : ItemsViewHandler _layoutPropertyChangedProxy?.Unsubscribe();
@@ -79,6 +83,9 @@ public static void MapItemSizingStrategy(StructuredItemsViewHandler
protected override ListViewBase SelectListViewBase()
{
+ _listViewItemStyle = GetDefaultStyle(ListViewItemStyleKey);
+ _gridViewItemStyle = GetDefaultStyle(GridViewItemStyleKey);
+
switch (VirtualView.ItemsLayout)
{
case GridItemsLayout gridItemsLayout:
@@ -242,6 +249,11 @@ static WStyle GetItemContainerStyle(GridItemsLayout layout)
var style = new WStyle(typeof(GridViewItem));
+ if (_gridViewItemStyle is not null)
+ {
+ style.BasedOn = _gridViewItemStyle;
+ }
+
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
@@ -249,6 +261,11 @@ static WStyle GetItemContainerStyle(GridItemsLayout layout)
return style;
}
+ static WStyle GetDefaultStyle(string resourceKey)
+ {
+ return Microsoft.UI.Xaml.Application.Current.Resources[resourceKey] as WStyle;
+ }
+
static WStyle GetVerticalItemContainerStyle(LinearItemsLayout layout)
{
var v = layout?.ItemSpacing ?? 0;
@@ -256,6 +273,11 @@ static WStyle GetVerticalItemContainerStyle(LinearItemsLayout layout)
var style = new WStyle(typeof(ListViewItem));
+ if (_listViewItemStyle is not null)
+ {
+ style.BasedOn = _listViewItemStyle;
+ }
+
style.Setters.Add(new WSetter(FrameworkElement.MinHeightProperty, 0));
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
@@ -271,6 +293,11 @@ static WStyle GetHorizontalItemContainerStyle(LinearItemsLayout layout)
var style = new WStyle(typeof(ListViewItem));
+ if (_listViewItemStyle is not null)
+ {
+ style.BasedOn = _listViewItemStyle;
+ }
+
style.Setters.Add(new WSetter(FrameworkElement.MinWidthProperty, 0));
style.Setters.Add(new WSetter(Control.PaddingProperty, padding));
style.Setters.Add(new WSetter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch));
diff --git a/src/Controls/src/Core/Items/CarouselLayoutTypeConverter.cs b/src/Controls/src/Core/Items/CarouselLayoutTypeConverter.cs
index 9bb0fe170d57..35621216186c 100644
--- a/src/Controls/src/Core/Items/CarouselLayoutTypeConverter.cs
+++ b/src/Controls/src/Core/Items/CarouselLayoutTypeConverter.cs
@@ -19,12 +19,12 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destina
if (strValue == "HorizontalList")
{
- return LinearItemsLayout.CarouselDefault;
+ return LinearItemsLayout.CreateCarouselHorizontalDefault();
}
if (strValue == "VerticalList")
{
- return LinearItemsLayout.CarouselVertical;
+ return LinearItemsLayout.CreateCarouselVerticalDefault();
}
throw new InvalidOperationException($"Cannot convert \"{strValue}\" into {typeof(LinearItemsLayout)}");
diff --git a/src/Controls/src/Core/Items/CarouselView.cs b/src/Controls/src/Core/Items/CarouselView.cs
index 95918e8efc3a..c83e81a7ce1d 100644
--- a/src/Controls/src/Core/Items/CarouselView.cs
+++ b/src/Controls/src/Core/Items/CarouselView.cs
@@ -187,7 +187,7 @@ public object PositionChangedCommandParameter
/// Bindable property for .
public static readonly BindableProperty ItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(LinearItemsLayout), typeof(ItemsView),
- LinearItemsLayout.CarouselDefault);
+ null, defaultValueCreator: (b) => LinearItemsLayout.CreateCarouselHorizontalDefault());
///
[System.ComponentModel.TypeConverter(typeof(CarouselLayoutTypeConverter))]
diff --git a/src/Controls/src/Core/Items/ItemsLayoutTypeConverter.cs b/src/Controls/src/Core/Items/ItemsLayoutTypeConverter.cs
index dc5f639d74a1..f65954431530 100644
--- a/src/Controls/src/Core/Items/ItemsLayoutTypeConverter.cs
+++ b/src/Controls/src/Core/Items/ItemsLayoutTypeConverter.cs
@@ -26,11 +26,11 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destina
if (strValue == "VerticalList")
{
- return LinearItemsLayout.Vertical;
+ return LinearItemsLayout.CreateVerticalDefault();
}
else if (strValue == "HorizontalList")
{
- return LinearItemsLayout.Horizontal;
+ return LinearItemsLayout.CreateHorizontalDefault();
}
else if (strValue.StartsWith("VerticalGrid", StringComparison.Ordinal))
{
diff --git a/src/Controls/src/Core/Items/ItemsView.cs b/src/Controls/src/Core/Items/ItemsView.cs
index fab7d27fd467..ca4f5b01ccc6 100644
--- a/src/Controls/src/Core/Items/ItemsView.cs
+++ b/src/Controls/src/Core/Items/ItemsView.cs
@@ -113,7 +113,8 @@ public int RemainingItemsThreshold
internal static readonly BindableProperty InternalItemsLayoutProperty =
BindableProperty.Create(nameof(ItemsLayout), typeof(IItemsLayout), typeof(ItemsView),
- LinearItemsLayout.Vertical, propertyChanged: OnInternalItemsLayoutPropertyChanged);
+ null, propertyChanged: OnInternalItemsLayoutPropertyChanged,
+ defaultValueCreator: (b) => LinearItemsLayout.CreateVerticalDefault());
static void OnInternalItemsLayoutPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
diff --git a/src/Controls/src/Core/Items/LinearItemsLayout.cs b/src/Controls/src/Core/Items/LinearItemsLayout.cs
index fc08ecc343c1..db4d46c9c1bc 100644
--- a/src/Controls/src/Core/Items/LinearItemsLayout.cs
+++ b/src/Controls/src/Core/Items/LinearItemsLayout.cs
@@ -12,22 +12,14 @@ public LinearItemsLayout([Parameter("Orientation")] ItemsLayoutOrientation orien
}
///
- public static readonly IItemsLayout Vertical = new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
+ public static readonly IItemsLayout Vertical = CreateVerticalDefault();
///
- public static readonly IItemsLayout Horizontal = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
+ public static readonly IItemsLayout Horizontal = CreateHorizontalDefault();
///
- public static readonly IItemsLayout CarouselVertical = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
- {
- SnapPointsType = SnapPointsType.MandatorySingle,
- SnapPointsAlignment = SnapPointsAlignment.Center
- };
+ public static readonly IItemsLayout CarouselVertical = CreateCarouselVerticalDefault();
- internal static readonly LinearItemsLayout CarouselDefault = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
- {
- SnapPointsType = SnapPointsType.MandatorySingle,
- SnapPointsAlignment = SnapPointsAlignment.Center
- };
+ internal static readonly LinearItemsLayout CarouselDefault = CreateCarouselHorizontalDefault();
/// Bindable property for .
public static readonly BindableProperty ItemSpacingProperty =
@@ -40,5 +32,25 @@ public double ItemSpacing
get => (double)GetValue(ItemSpacingProperty);
set => SetValue(ItemSpacingProperty, value);
}
+
+ internal static LinearItemsLayout CreateVerticalDefault()
+ => new LinearItemsLayout(ItemsLayoutOrientation.Vertical);
+
+ internal static LinearItemsLayout CreateHorizontalDefault()
+ => new LinearItemsLayout(ItemsLayoutOrientation.Horizontal);
+
+ internal static LinearItemsLayout CreateCarouselVerticalDefault()
+ => new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
+ {
+ SnapPointsType = SnapPointsType.MandatorySingle,
+ SnapPointsAlignment = SnapPointsAlignment.Center
+ };
+
+ internal static LinearItemsLayout CreateCarouselHorizontalDefault()
+ => new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
+ {
+ SnapPointsType = SnapPointsType.MandatorySingle,
+ SnapPointsAlignment = SnapPointsAlignment.Center
+ };
}
}
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
index 869def3ea434..dd9b4164a2a2 100644
--- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
@@ -1,4 +1,5 @@
-#nullable enable
+#nullable enable
+*REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer.ViewWillLayoutSubviews() -> void
*REMOVED*Microsoft.Maui.Controls.Accelerator
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.get -> System.Collections.Generic.IEnumerable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
index 869def3ea434..dd9b4164a2a2 100644
--- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
@@ -1,4 +1,5 @@
-#nullable enable
+#nullable enable
+*REMOVED*override Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer.ViewWillLayoutSubviews() -> void
*REMOVED*Microsoft.Maui.Controls.Accelerator
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.get -> System.Collections.Generic.IEnumerable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
diff --git a/src/Controls/tests/Core.UnitTests/ItemsLayoutTypeConverterTests.cs b/src/Controls/tests/Core.UnitTests/ItemsLayoutTypeConverterTests.cs
index 63dc04ab9507..c63229840874 100644
--- a/src/Controls/tests/Core.UnitTests/ItemsLayoutTypeConverterTests.cs
+++ b/src/Controls/tests/Core.UnitTests/ItemsLayoutTypeConverterTests.cs
@@ -11,7 +11,10 @@ public void HorizontalListShouldReturnLinearItemsLayout()
{
var converter = new ItemsLayoutTypeConverter();
var result = converter.ConvertFromInvariantString("HorizontalList");
- Assert.Same(LinearItemsLayout.Horizontal, result);
+
+ Assert.IsType(result);
+ var linearLayout = (LinearItemsLayout)result;
+ Assert.Equal(ItemsLayoutOrientation.Horizontal, linearLayout.Orientation);
}
[Fact]
@@ -19,7 +22,10 @@ public void VerticalListShouldReturnLinearItemsLayout()
{
var converter = new ItemsLayoutTypeConverter();
var result = converter.ConvertFromInvariantString("VerticalList");
- Assert.Same(LinearItemsLayout.Vertical, result);
+
+ Assert.IsType(result);
+ var linearLayout = (LinearItemsLayout)result;
+ Assert.Equal(ItemsLayoutOrientation.Vertical, linearLayout.Orientation);
}
[Fact]
diff --git a/src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.iOS.cs
index 97ab3a259670..7675d1dd2fc8 100644
--- a/src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.iOS.cs
+++ b/src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.iOS.cs
@@ -1,7 +1,54 @@
-namespace Microsoft.Maui.DeviceTests
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Handlers.Items2;
+using Microsoft.Maui.Handlers;
+using Xunit;
+
+namespace Microsoft.Maui.DeviceTests
{
public partial class CarouselViewTests
{
+ [Fact(DisplayName = "CarouselView Does Not Leak With Default ItemsLayout")]
+ public async Task CarouselViewDoesNotLeakWithDefaultItemsLayout()
+ {
+ SetupBuilder();
+
+ WeakReference weakCarouselView = null;
+ WeakReference weakHandler = null;
+
+ await InvokeOnMainThreadAsync(async () =>
+ {
+ var carouselView = new CarouselView
+ {
+ ItemsSource = new List { "Item 1", "Item 2", "Item 3" },
+ ItemTemplate = new DataTemplate(() => new Label())
+ // Note: Not setting ItemsLayout - using the default
+ };
+
+ weakCarouselView = new WeakReference(carouselView);
+
+ var handler = await CreateHandlerAsync(carouselView);
+
+ // Verify handler is created
+ Assert.NotNull(handler);
+
+ // Store weak reference to the handler
+ weakHandler = new WeakReference(handler);
+
+ // Disconnect the handler
+ ((IElementHandler)handler).DisconnectHandler();
+ });
+
+ // Force garbage collection
+ await AssertionExtensions.WaitForGC(weakCarouselView, weakHandler);
+
+ // Verify the CarouselView was collected
+ Assert.False(weakCarouselView.IsAlive, "CarouselView should have been garbage collected");
+ // Verify the handler was collected
+ Assert.False(weakHandler.IsAlive, "CarouselViewHandler2 should have been garbage collected");
+ }
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs
index 431454c9d4b6..1a9dfd28b7ce 100644
--- a/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs
+++ b/src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.iOS.cs
@@ -251,6 +251,47 @@ public void IndexPathValidTest()
Assert.False(source.IsIndexPathValid(invalidSection));
}
+ [Fact(DisplayName = "CollectionView Does Not Leak With Default ItemsLayout")]
+ public async Task CollectionViewDoesNotLeakWithDefaultItemsLayout()
+ {
+ SetupBuilder();
+
+ WeakReference weakCollectionView = null;
+ WeakReference weakHandler = null;
+
+ await InvokeOnMainThreadAsync(async () =>
+ {
+ var collectionView = new CollectionView
+ {
+ ItemsSource = new List { "Item 1", "Item 2", "Item 3" },
+ ItemTemplate = new DataTemplate(() => new Label())
+ // Note: Not setting ItemsLayout - using the default
+ };
+
+ weakCollectionView = new WeakReference(collectionView);
+
+ var handler = await CreateHandlerAsync(collectionView);
+
+ // Verify handler is created
+ Assert.NotNull(handler);
+
+ // Store weak reference to the handler
+ weakHandler = new WeakReference(handler);
+
+ // Disconnect the handler
+ ((IElementHandler)handler).DisconnectHandler();
+ });
+
+ // Force garbage collection
+ await AssertionExtensions.WaitForGC(weakCollectionView, weakHandler);
+
+ // Verify the CollectionView was collected
+ Assert.False(weakCollectionView.IsAlive, "CollectionView should have been garbage collected");
+
+ // Verify the handler was collected
+ Assert.False(weakHandler.IsAlive, "CollectionViewHandler2 should have been garbage collected");
+ }
+
///
/// Simulates what a developer might do with a Page/View
///
diff --git a/src/Controls/tests/SourceGen.UnitTests/CultureTestsCollection.cs b/src/Controls/tests/SourceGen.UnitTests/CultureTestsCollection.cs
new file mode 100644
index 000000000000..40716785eba2
--- /dev/null
+++ b/src/Controls/tests/SourceGen.UnitTests/CultureTestsCollection.cs
@@ -0,0 +1,8 @@
+using Xunit;
+
+namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
+
+[CollectionDefinition("CultureTests", DisableParallelization = true)]
+public class CultureTestsCollection
+{
+}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/BasicCase.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/BasicCase.cs
index 9ebc4b46ff6f..53079c485dfa 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/BasicCase.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/BasicCase.cs
@@ -1,11 +1,11 @@
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class BasicCase : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void BasicXaml()
{
var xaml =
@@ -84,8 +84,8 @@ private partial void InitializeComponent()
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.Equal(expected, generated);
}
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/CompiledBindings.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/CompiledBindings.cs
index ad78118bacf0..5e85319f1595 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/CompiledBindings.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/CompiledBindings.cs
@@ -1,13 +1,13 @@
using System;
using System.IO;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class CompiledBindings : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void CanDetectXDataType()
{
var xaml =
@@ -160,7 +160,7 @@ static bool ShouldUseSetter(global::Microsoft.Maui.Controls.BindingMode mode)
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.False(result.Diagnostics.Any());
+ Assert.Equal(expected, generated);
}
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/DoesNotFail.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/DoesNotFail.cs
index f30637a3ef6d..c8a747642d6c 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/DoesNotFail.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/DoesNotFail.cs
@@ -1,11 +1,11 @@
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class DoesNotFail : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void Test()
{
var xaml =
@@ -48,7 +48,7 @@ public TestPage()
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
// Assert.AreEqual(expected, generated);
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/LineInfoTests.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/LineInfoTests.cs
index 414fb623b245..9d734051b192 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/LineInfoTests.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/LineInfoTests.cs
@@ -1,13 +1,13 @@
using System;
using System.IO;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class LineInfoTests : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void DiagnosticShowsLocationInInputXamlFile()
{
var xaml =
@@ -31,6 +31,6 @@ public void DiagnosticShowsLocationInInputXamlFile()
var generatedCode = result.GeneratedTrees.Single(tree => Path.GetFileName(tree.FilePath) == "Test.xaml.xsg.cs").ToString();
var expectedFilePath = Path.Combine(Environment.CurrentDirectory, "Test.xaml");
- Assert.IsTrue(generatedCode.Contains(@$"#line 9 ""{expectedFilePath}""", StringComparison.Ordinal));
+ Assert.True(generatedCode.Contains(@$"#line 9 ""{expectedFilePath}""", StringComparison.Ordinal));
}
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/ResourceDictionary.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/ResourceDictionary.cs
index 2ebccb583076..638abd4d7595 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/ResourceDictionary.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/ResourceDictionary.cs
@@ -1,11 +1,11 @@
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class ResourceDictionary : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void ResourceDictionaryWithoutXClass()
{
var xaml =
@@ -51,9 +51,9 @@ private partial void InitializeComponent()
""";
var (result, generated) = RunGenerator(xaml, "", path: "Styles.xaml");
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.Equal(expected, generated);
}
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetBinding.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetBinding.cs
index ca8ea28a03ad..5201064c6e91 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetBinding.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetBinding.cs
@@ -1,13 +1,13 @@
using System;
using System.IO;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class SetBinding : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void Test()
{
var xaml =
@@ -81,7 +81,7 @@ private partial void InitializeComponent()
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.False(result.Diagnostics.Any());
+ Assert.Equal(expected, generated);
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetValue.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetValue.cs
index efe409a667d8..4dd70c7dfb4c 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetValue.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SetValue.cs
@@ -1,12 +1,12 @@
using System.Linq;
using Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class SetValue : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void Test()
{
var xaml =
@@ -39,7 +39,7 @@ public TestPage()
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SimplifyOnPlatform.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SimplifyOnPlatform.cs
index d604603923d3..04c61499ee90 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SimplifyOnPlatform.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/SimplifyOnPlatform.cs
@@ -1,13 +1,13 @@
using System;
using System.IO;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class SimplifyOnPlatform : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void Test()
{
var xaml =
@@ -166,8 +166,8 @@ private partial void InitializeComponent()
""";
var (result, generated) = RunGenerator(xaml, code, targetFramework: "net10.0-android");
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.Equal(expected, generated);
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/WarningIgnore.cs b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/WarningIgnore.cs
index 2044bddffce6..baf02d4a1b41 100644
--- a/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/WarningIgnore.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/InitializeComponent/WarningIgnore.cs
@@ -1,11 +1,11 @@
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class CSWarningIgnore : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void WarningIgnore()
{
var xaml =
@@ -86,8 +86,8 @@ private partial void InitializeComponent()
""";
var (result, generated) = RunGenerator(xaml, code, "0168, CS0612");
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
- Assert.AreEqual(expected, generated);
+ Assert.Equal(expected, generated);
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/KnownTypeConvertersTests.cs b/src/Controls/tests/SourceGen.UnitTests/KnownTypeConvertersTests.cs
index aa3e65f490e4..e0b47aaefd0f 100644
--- a/src/Controls/tests/SourceGen.UnitTests/KnownTypeConvertersTests.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/KnownTypeConvertersTests.cs
@@ -1,26 +1,24 @@
+using System;
using System.Globalization;
-using NUnit.Framework;
using Microsoft.CodeAnalysis;
using System.Linq;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests
{
- [TestFixture]
- [NonParallelizable]
- public class KnownTypeConvertersTests : SourceGenXamlInitializeComponentTestBase
+ [Collection("CultureTests")]
+ public class KnownTypeConvertersTests : SourceGenXamlInitializeComponentTestBase, IDisposable
{
- private CultureInfo? _originalCulture;
- private CultureInfo? _originalUICulture;
+ private readonly CultureInfo? _originalCulture;
+ private readonly CultureInfo? _originalUICulture;
- [SetUp]
- public void SetUp()
+ public KnownTypeConvertersTests()
{
_originalCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
_originalUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
}
- [TearDown]
- public void TearDown()
+ void IDisposable.Dispose()
{
if (_originalCulture is not null)
{
@@ -33,11 +31,12 @@ public void TearDown()
}
}
- [TestCase("en-US", "1.5*")]
- [TestCase("fr-FR", "2.5*")]
- [TestCase("de-DE", "3.14*")]
- [TestCase("es-ES", "0.75*")]
- [TestCase("ru-RU", "1.414*")]
+ [Theory]
+ [InlineData("en-US", "1.5*")]
+ [InlineData("fr-FR", "2.5*")]
+ [InlineData("de-DE", "3.14*")]
+ [InlineData("es-ES", "0.75*")]
+ [InlineData("ru-RU", "1.414*")]
public void GridLengthTypeConverter_StarValues_ProducesConsistentOutput_AcrossCultures(string cultureName, string gridLengthValue)
{
// Set both current and UI cultures to test locale
@@ -75,27 +74,29 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
// Should not have any diagnostics/errors
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
// The generated code should contain a properly formatted GridLength with period as decimal separator
// regardless of the current culture
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// Extract the numeric value from the input (e.g., "2.5*" -> "2.5")
var numericPart = gridLengthValue.Substring(0, gridLengthValue.Length - 1);
// The generated code should use period as decimal separator (culture-invariant)
// and should contain the GridLength constructor with Star unit type
- Assert.That(generated, Does.Contain($"new global::Microsoft.Maui.GridLength({numericPart}, global::Microsoft.Maui.GridUnitType.Star)"),
+ Assert.True(generated!.Contains($"new global::Microsoft.Maui.GridLength({numericPart}, global::Microsoft.Maui.GridUnitType.Star)", StringComparison.Ordinal),
$"Generated code should contain culture-invariant GridLength with value {numericPart}. Generated code: {generated}");
}
- [TestCase("en-US", "100.5")]
- [TestCase("fr-FR", "200.25")]
- [TestCase("de-DE", "50.75")]
- [TestCase("es-ES", "150.125")]
- [TestCase("ru-RU", "75.875")]
- public void GridLengthTypeConverter_AbsoluteValues_ProducesConsistentOutput_AcrossCultures(string cultureName, string gridLengthValue)
+ [Theory]
+ [InlineData("en-US", "100.5")]
+ [InlineData("fr-FR", "200.25")]
+ [InlineData("de-DE", "50.75")]
+ [InlineData("es-ES", "150.125")]
+ [InlineData("ru-RU", "75.875")]
+ public void GridLengthTypeConverter_AbsoluteValues_ProducesConsistentOutput_AcrossCultures(string cultureName, string gridLengthValue)
{
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(cultureName);
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
@@ -130,22 +131,23 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// The generated code should use period as decimal separator and Absolute unit type
- Assert.That(generated, Does.Contain($"new global::Microsoft.Maui.GridLength({gridLengthValue}, global::Microsoft.Maui.GridUnitType.Absolute)"),
+ Assert.True(generated!.Contains($"new global::Microsoft.Maui.GridLength({gridLengthValue}, global::Microsoft.Maui.GridUnitType.Absolute)", StringComparison.Ordinal),
$"Generated code should contain culture-invariant GridLength with absolute value {gridLengthValue}. Generated code: {generated}");
}
- [TestCase("en-US")]
- [TestCase("fr-FR")]
- [TestCase("de-DE")]
- [TestCase("es-ES")]
- [TestCase("ru-RU")]
- public void GridLengthTypeConverter_SpecialValues_ProducesConsistentOutput_AcrossCultures(string cultureName)
+ [Theory]
+ [InlineData("en-US")]
+ [InlineData("fr-FR")]
+ [InlineData("de-DE")]
+ [InlineData("es-ES")]
+ [InlineData("ru-RU")]
+ public void GridLengthTypeConverter_SpecialValues_ProducesConsistentOutput_AcrossCultures(string cultureName)
{
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(cultureName);
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
@@ -185,19 +187,19 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// Check for special values that should be culture-independent
- Assert.That(generated, Does.Contain("global::Microsoft.Maui.GridLength.Star"),
+ Assert.True(generated!.Contains("global::Microsoft.Maui.GridLength.Star", StringComparison.Ordinal),
"Generated code should contain GridLength.Star for '*' values");
- Assert.That(generated, Does.Contain("global::Microsoft.Maui.GridLength.Auto"),
+ Assert.True(generated.Contains("global::Microsoft.Maui.GridLength.Auto", StringComparison.Ordinal),
"Generated code should contain GridLength.Auto for 'Auto' values");
}
- [Test]
+ [Fact]
public void GridLengthTypeConverter_StarValue_GeneratesGridLengthStar()
{
const string xaml = """
@@ -233,17 +235,17 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// Should generate GridLength.Star for "*" value
- Assert.That(generated, Does.Contain("global::Microsoft.Maui.GridLength.Star"),
+ Assert.True(generated!.Contains("global::Microsoft.Maui.GridLength.Star", StringComparison.Ordinal),
"Generated code should contain GridLength.Star for '*' value");
}
- [Test]
+ [Fact]
public void GridLengthTypeConverter_AutoValue_GeneratesGridLengthAuto()
{
const string xaml = """
@@ -279,17 +281,17 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// Should generate GridLength.Auto for "Auto" value
- Assert.That(generated, Does.Contain("global::Microsoft.Maui.GridLength.Auto"),
+ Assert.True(generated!.Contains("global::Microsoft.Maui.GridLength.Auto", StringComparison.Ordinal),
"Generated code should contain GridLength.Auto for 'Auto' value");
}
- [Test]
+ [Fact]
public void EnumTypeConverter()
{
const string xaml = """
@@ -321,13 +323,13 @@ public TestPage()
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
+ Assert.False(result.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error),
$"Generated code should not have errors. Diagnostics: {string.Join(", ", result.Diagnostics.Select(d => d.ToString()))}");
- Assert.IsNotNull(generated, "Generated code should not be null");
+ Assert.NotNull(generated);
// Should generate FlexDirection.Row for "Row" value
- Assert.That(generated, Does.Contain("flexLayout.SetValue(global::Microsoft.Maui.Controls.FlexLayout.DirectionProperty, global::Microsoft.Maui.Layouts.FlexDirection.Row);"),
+ Assert.True(generated!.Contains("flexLayout.SetValue(global::Microsoft.Maui.Controls.FlexLayout.DirectionProperty, global::Microsoft.Maui.Layouts.FlexDirection.Row);", StringComparison.Ordinal),
"Generated code should contain FlexDirection.Row for 'Row' value");
}
}
diff --git a/src/Controls/tests/SourceGen.UnitTests/NamingHelpersTests.cs b/src/Controls/tests/SourceGen.UnitTests/NamingHelpersTests.cs
index 0a1496dedd50..50a5b5693901 100644
--- a/src/Controls/tests/SourceGen.UnitTests/NamingHelpersTests.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/NamingHelpersTests.cs
@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
@@ -26,20 +26,20 @@ public class TestClass
""";
- [Test]
+ [Fact]
public void CreateVariableName()
{
var compilation = SourceGeneratorDriver.CreateMauiCompilation();
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code));
var context = new object();
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(context, compilation.GetTypeByMetadataName("Test.TestClass")!), Is.EqualTo("testClass"));
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(context, compilation.GetTypeByMetadataName("Test.TestClass")!), Is.EqualTo("testClass1"));
+ Assert.Equal("testClass", NamingHelpers.CreateUniqueVariableNameImpl(context, compilation.GetTypeByMetadataName("Test.TestClass")!));
+ Assert.Equal("testClass1", NamingHelpers.CreateUniqueVariableNameImpl(context, compilation.GetTypeByMetadataName("Test.TestClass")!));
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass`1")!), Is.EqualTo("testClass"));
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass`1")!.Construct(compilation.GetTypeByMetadataName("Test.TestClass")!)), Is.EqualTo("testClass"));
+ Assert.Equal("testClass", NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass`1")!));
+ Assert.Equal("testClass", NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass`1")!.Construct(compilation.GetTypeByMetadataName("Test.TestClass")!)));
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.CreateArrayTypeSymbol(compilation.GetTypeByMetadataName("Test.TestClass")!)!), Is.EqualTo("testClassArray"));
+ Assert.Equal("testClassArray", NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.CreateArrayTypeSymbol(compilation.GetTypeByMetadataName("Test.TestClass")!)!));
- Assert.That(NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass+Nested")!), Is.EqualTo("nested"));
+ Assert.Equal("nested", NamingHelpers.CreateUniqueVariableNameImpl(new object(), compilation.GetTypeByMetadataName("Test.TestClass+Nested")!));
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/NoBaseClassOnCodeBehind.cs b/src/Controls/tests/SourceGen.UnitTests/NoBaseClassOnCodeBehind.cs
index fb0e489e9bce..f95b3fd22b4b 100644
--- a/src/Controls/tests/SourceGen.UnitTests/NoBaseClassOnCodeBehind.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/NoBaseClassOnCodeBehind.cs
@@ -1,12 +1,12 @@
using System;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class NoBaseClassOnCodeBehind : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
//as the base class ContentPage is only defined in the sg.cs,
//it's not part of the compilation when we generate initializecomponent, and the Resources property can't be found
public void CodeBehindWithNoBaseClass()
@@ -44,6 +44,6 @@ public TestPage()
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/NullableProperties.cs b/src/Controls/tests/SourceGen.UnitTests/NullableProperties.cs
index 960ef0c76bda..c62457706719 100644
--- a/src/Controls/tests/SourceGen.UnitTests/NullableProperties.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/NullableProperties.cs
@@ -1,13 +1,13 @@
using System;
using System.Linq;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.SourceGen.UnitTests;
public class NullableProperties : SourceGenXamlInitializeComponentTestBase
{
- [Test]
+ [Fact]
public void NullableStringPropertyShouldWork()
{
var xaml =
@@ -52,9 +52,9 @@ public class EventToCommandBehavior : Behavior
""";
var (result, generated) = RunGenerator(xaml, code);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
- Assert.IsTrue(generated?.Contains("Test.EventToCommandBehavior", StringComparison.Ordinal));
- Assert.IsTrue(generated?.Contains("eventToCommandBehavior.SetValue(global::Test.EventToCommandBehavior.EventNameProperty", StringComparison.Ordinal));
+ Assert.True(generated?.Contains("Test.EventToCommandBehavior", StringComparison.Ordinal) ?? false);
+ Assert.True(generated?.Contains("eventToCommandBehavior.SetValue(global::Test.EventToCommandBehavior.EventNameProperty", StringComparison.Ordinal) ?? false);
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj b/src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj
index 3dff5a2aa1d0..ad24995ffe37 100644
--- a/src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj
+++ b/src/Controls/tests/SourceGen.UnitTests/SourceGen.UnitTests.csproj
@@ -24,8 +24,11 @@
-
-
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
diff --git a/src/Controls/tests/SourceGen.UnitTests/SourceGenCssTests.cs b/src/Controls/tests/SourceGen.UnitTests/SourceGenCssTests.cs
index 2cffaae46b57..b496dafc567d 100644
--- a/src/Controls/tests/SourceGen.UnitTests/SourceGenCssTests.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/SourceGenCssTests.cs
@@ -3,7 +3,7 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Maui.Controls.SourceGen;
-using NUnit.Framework;
+using Xunit;
using static Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen.SourceGeneratorDriver;
@@ -14,7 +14,7 @@ public class SourceGenCssTests : SourceGenTestsBase
private record AdditionalCssFile(string Path, string Content, string? RelativePath = null, string? TargetPath = null, string? ManifestResourceName = null, string? TargetFramework = null)
: AdditionalFile(Text: SourceGeneratorDriver.ToAdditionalText(Path, Content), Kind: "Css", RelativePath: RelativePath ?? Path, TargetPath: TargetPath, ManifestResourceName: ManifestResourceName ?? Path, TargetFramework: TargetFramework, NoWarn: "");
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_BasicCss()
{
var css =
@@ -28,14 +28,14 @@ public void TestCodeBehindGenerator_BasicCss()
var cssFile = new AdditionalCssFile("Test.css", css);
var result = SourceGeneratorDriver.RunGenerator(compilation, cssFile);
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
- Assert.IsTrue(generated.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));
+ Assert.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", generated, StringComparison.Ordinal);
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_ModifiedCss()
{
var css =
@@ -61,10 +61,10 @@ public void TestCodeBehindGenerator_ModifiedCss()
var output1 = result1.GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
var output2 = result2.GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
- // Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
- Assert.AreEqual(output1, output2);
+ // Assert.True(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
+ Assert.Equal(output1, output2);
- Assert.IsTrue(output1.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));
+ Assert.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", output1, StringComparison.Ordinal);
(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
diff --git a/src/Controls/tests/SourceGen.UnitTests/SourceGenTestsBase.cs b/src/Controls/tests/SourceGen.UnitTests/SourceGenTestsBase.cs
index 7d6f98b41679..31cb265168fc 100644
--- a/src/Controls/tests/SourceGen.UnitTests/SourceGenTestsBase.cs
+++ b/src/Controls/tests/SourceGen.UnitTests/SourceGenTestsBase.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
-using NUnit.Framework;
+using Xunit;
namespace Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen;
@@ -12,7 +12,7 @@ public static void VerifyStepRunReasons(GeneratorRunResult result2, Dictionary(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
- Assert.IsTrue(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
- Assert.IsTrue(generated.Contains("public partial class TestPage : global::Microsoft.Maui.Controls.ContentPage", StringComparison.Ordinal));
+ Assert.True(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
+ Assert.True(generated.Contains("public partial class TestPage : global::Microsoft.Maui.Controls.ContentPage", StringComparison.Ordinal));
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_GlobalNamespace()
{
var xaml =
@@ -54,14 +54,14 @@ public void TestCodeBehindGenerator_GlobalNamespace()
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText("[assembly: global::Microsoft.Maui.Controls.Xaml.Internals.AllowImplicitXmlnsDeclaration]"));
var result = SourceGeneratorDriver.RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
- Assert.IsTrue(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
+ Assert.True(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_AggregatedXmlns()
{
var xaml =
@@ -84,15 +84,15 @@ public void TestCodeBehindGenerator_AggregatedXmlns()
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code));
var result = RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs")).SourceText.ToString();
- Assert.IsTrue(generated.Contains("Microsoft.Maui.Controls.ContentPage", StringComparison.Ordinal));
- Assert.IsTrue(generated.Contains("global::Microsoft.Maui.Controls.Label label", StringComparison.Ordinal));
+ Assert.True(generated.Contains("Microsoft.Maui.Controls.ContentPage", StringComparison.Ordinal));
+ Assert.True(generated.Contains("global::Microsoft.Maui.Controls.Label label", StringComparison.Ordinal));
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_AggregatedXmlnsOnRD()
{
var xaml =
@@ -114,14 +114,17 @@ public void TestCodeBehindGenerator_AggregatedXmlnsOnRD()
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code));
var result = RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs")).SourceText.ToString();
- Assert.IsTrue(generated.Contains("public partial class __Type", StringComparison.Ordinal));
+ Assert.True(generated.Contains("public partial class __Type", StringComparison.Ordinal));
}
- public void TestCodeBehindGenerator_LocalXaml([Values] bool resolvedType)
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void TestCodeBehindGenerator_LocalXaml(bool resolvedType)
{
var xaml =
"""
@@ -165,19 +168,19 @@ public class TestControl : ContentView
if (resolvedType)
{
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
- Assert.IsTrue(generated.Contains("Test.TestControl MyTestControl", StringComparison.Ordinal));
+ Assert.True(generated.Contains("Test.TestControl MyTestControl", StringComparison.Ordinal));
}
else
{
- Assert.IsTrue(result.Diagnostics.Any(d => d.Descriptor.Id == "MAUIX2000"));
+ Assert.True(result.Diagnostics.Any(d => d.Descriptor.Id == "MAUIX2000"));
}
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_CompilationClone()
{
var xaml =
@@ -200,7 +203,7 @@ public void TestCodeBehindGenerator_CompilationClone()
var output2 = result2.GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
// Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
- Assert.AreEqual(output1, output2);
+ Assert.Equal(output1, output2);
(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
@@ -220,7 +223,7 @@ public void TestCodeBehindGenerator_CompilationClone()
VerifyStepRunReasons(result2, expectedReasons);
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_ReferenceAdded()
{
var xaml =
@@ -243,7 +246,7 @@ public void TestCodeBehindGenerator_ReferenceAdded()
var output2 = result2.GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
// Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
- Assert.AreEqual(output1, output2);
+ Assert.Equal(output1, output2);
(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
@@ -263,7 +266,7 @@ public void TestCodeBehindGenerator_ReferenceAdded()
VerifyStepRunReasons(result2, expectedReasons);
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_ModifiedXaml()
{
var xaml =
@@ -297,12 +300,12 @@ public void TestCodeBehindGenerator_ModifiedXaml()
var output2 = result2.GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs", StringComparison.OrdinalIgnoreCase)).SourceText.ToString();
// Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
- Assert.AreNotEqual(output1, output2);
+ Assert.NotEqual(output1, output2);
- Assert.IsTrue(output1.Contains("MyButton", StringComparison.Ordinal));
- Assert.IsFalse(output1.Contains("MyButton2", StringComparison.Ordinal));
- Assert.IsTrue(output2.Contains("MyButton", StringComparison.Ordinal));
- Assert.IsTrue(output2.Contains("MyButton2", StringComparison.Ordinal));
+ Assert.True(output1.Contains("MyButton", StringComparison.Ordinal));
+ Assert.False(output1.Contains("MyButton2", StringComparison.Ordinal));
+ Assert.True(output2.Contains("MyButton", StringComparison.Ordinal));
+ Assert.True(output2.Contains("MyButton2", StringComparison.Ordinal));
(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
@@ -324,7 +327,7 @@ public void TestCodeBehindGenerator_ModifiedXaml()
VerifyStepRunReasons(result2, expectedReasons);
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_NotXaml()
{
var xaml =
@@ -338,10 +341,10 @@ public void TestCodeBehindGenerator_NotXaml()
var result = SourceGeneratorDriver.RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs")).SourceText.ToString();
- Assert.That(result.Diagnostics.Any() || string.IsNullOrWhiteSpace(generated));
+ Assert.True(result.Diagnostics.Any() || string.IsNullOrWhiteSpace(generated));
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_ConflictingNames()
{
var code =
@@ -378,12 +381,12 @@ public class Conflicting : Label { }
var result = SourceGeneratorDriver.RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsTrue(result.Diagnostics.Any());
+ Assert.True(result.Diagnostics.Any());
//var generated = result.Results.Single().GeneratedSources.Single().SourceText.ToString();
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_DuplicateNames()
{
var xaml = """
@@ -472,14 +475,14 @@ internal class InternalWithSuffix : Button { }
var result = SourceGeneratorDriver.RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs")).SourceText.ToString();
- Assert.IsTrue(generated.Contains("External.PublicInExternal publicInExternal", StringComparison.Ordinal));
+ Assert.True(generated.Contains("External.PublicInExternal publicInExternal", StringComparison.Ordinal));
}
- [Test]
+ [Fact]
public void TestCodeBehindGenerator_InternalsVisibleTo()
{
var xaml = """
@@ -538,10 +541,10 @@ internal class InternalButVisible : Label { }
var result = SourceGeneratorDriver.RunGenerator(compilation, new AdditionalXamlFile("Test.xaml", xaml));
- Assert.IsFalse(result.Diagnostics.Any());
+ Assert.False(result.Diagnostics.Any());
var generated = result.Results.Single().GeneratedSources.Single(gs => gs.HintName.EndsWith(".sg.cs")).SourceText.ToString();
- Assert.IsTrue(generated.Contains("External.InternalButVisible internalButVisible", StringComparison.Ordinal));
+ Assert.True(generated.Contains("External.InternalButVisible internalButVisible", StringComparison.Ordinal));
}
}
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnDarkTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnDarkTheme.png
new file mode 100644
index 000000000000..78c264d7b70e
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnLightTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnLightTheme.png
new file mode 100644
index 000000000000..6cc55517b404
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/CollectionViewSelectionModeOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..742566c1a0d5
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..62d224ce5055
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..386b8b0bc2a4
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..1f94e347f83f
Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue12134.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue12134.cs
index 4a27ffcc3468..afdc150bb9de 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue12134.cs
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue12134.cs
@@ -85,7 +85,7 @@ private WebView GetWebView()
SetCookieContainer(anotherWebView);
anotherWebView.Navigated += WebViewOnNavigated;
- anotherWebView.Source = "https://dotnet.microsoft.com/apps/xamarin";
+ anotherWebView.Source = "https://dotnet.microsoft.com";
return anotherWebView;
}
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue18443.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue18443.xaml
index 51fb6eaf19c7..2aefca703aa4 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue18443.xaml
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue18443.xaml
@@ -4,6 +4,6 @@
x:Class="Maui.Controls.Sample.Issues.Issue18443"
SafeAreaEdges="Container">
-
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue30868.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue30868.cs
new file mode 100644
index 000000000000..cb6ae9902230
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue30868.cs
@@ -0,0 +1,46 @@
+using System.Collections.ObjectModel;
+
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, 30868, "CollectionView selection visual states", PlatformAffected.UWP)]
+public class Issue30868 : ContentPage
+{
+ public ObservableCollection Items { get; set; }
+
+ public Issue30868()
+ {
+ Items = new ObservableCollection
+ {
+ "Item 1",
+ "Item 2",
+ "Item 3"
+ };
+
+ var collectionView = new CollectionView
+ {
+ ItemsSource = Items,
+ SelectionMode = SelectionMode.Multiple,
+ HeightRequest = 40,
+ AutomationId = "collectionViewSelectionMode",
+ ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Horizontal)
+ {
+ ItemSpacing = 4
+ },
+ ItemTemplate = new DataTemplate(() =>
+ {
+ var label = new Label
+ {
+ FontSize = 16,
+ VerticalOptions = LayoutOptions.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ Padding = new Thickness(10, 0, 10, 10),
+ TextColor = Colors.Purple
+ };
+ label.SetBinding(Label.TextProperty, ".");
+ return label;
+ })
+ };
+
+ Content = collectionView;
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue31372.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue31372.cs
new file mode 100644
index 000000000000..200d0da29507
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue31372.cs
@@ -0,0 +1,59 @@
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, 31372, "IsPresented=true Not Working on Initial Value in FlyoutPage", PlatformAffected.UWP | PlatformAffected.macOS)]
+
+public class Issue31372 : NavigationPage
+{
+ public Issue31372()
+ {
+ PushAsync(new Issue31372Page());
+ }
+}
+
+public class Issue31372Page : FlyoutPage
+{
+ public Issue31372Page()
+ {
+
+ // Create Flyout Page
+ var flyoutPage = new ContentPage
+ {
+ Title = "Flyout",
+ Content = new StackLayout
+ {
+ Children =
+ {
+ new Label
+ {
+ Text = "This is Flyout",
+ AutomationId = "FlyoutLabel"
+ }
+ }
+ }
+ };
+
+ // Create Detail Page
+ var detailPage = new ContentPage
+ {
+ Title = "Detailpage",
+ Content = new StackLayout
+ {
+ Padding = 16,
+ Spacing = 16,
+ Children =
+ {
+ new Label
+ {
+ Text = "This is Detail Page which displays additional information."
+ },
+ }
+ }
+ };
+
+ // Assign Flyout and Detail
+ Flyout = flyoutPage;
+ Detail = new NavigationPage(detailPage);
+ FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover;
+ IsPresented = true;
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue31731.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue31731.cs
new file mode 100644
index 000000000000..6a2100d681dd
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue31731.cs
@@ -0,0 +1,89 @@
+namespace Maui.Controls.Sample.Issues
+{
+ [Issue(IssueTracker.Github, 31731, "Picker dialog causes crash when page is popped while dialog is open", PlatformAffected.Android)]
+ public class Issue31731 : NavigationPage
+ {
+ public Issue31731() : base(new MainPage())
+ {
+ }
+
+ public class MainPage : ContentPage
+ {
+ public MainPage()
+ {
+ var button = new Button
+ {
+ Text = "Navigate to Picker Page",
+ AutomationId = "navigateButton"
+ };
+
+ button.Clicked += OnNavigateClicked;
+
+ var statusLabel = new Label
+ {
+ Text = "Status: Ready",
+ AutomationId = "statusLabel"
+ };
+
+ Content = new StackLayout
+ {
+ Padding = new Thickness(20),
+ Children = { statusLabel, button }
+ };
+ }
+
+ private void OnNavigateClicked(object sender, EventArgs e)
+ {
+ Navigation.PushAsync(new PickerPage());
+ }
+ }
+
+ public class PickerPage : ContentPage
+ {
+ public PickerPage()
+ {
+ var picker = new Picker
+ {
+ Title = "Select a color",
+ ItemsSource = new List { "Red", "Green", "Blue", "Yellow", "Purple" },
+ AutomationId = "colorPicker"
+ };
+
+ var instructionsLabel = new Label
+ {
+ Text = "Tap the picker to open the dialog, then wait for auto navigation back (3 seconds). The app should not crash.",
+ AutomationId = "instructionsLabel",
+ Margin = new Thickness(0, 0, 0, 20)
+ };
+
+ var statusLabel = new Label
+ {
+ Text = "Status: Page loaded",
+ AutomationId = "pageStatusLabel"
+ };
+
+ Content = new StackLayout
+ {
+ Padding = new Thickness(20),
+ Children = { instructionsLabel, statusLabel, picker }
+ };
+ }
+
+ protected override void OnNavigatedTo(NavigatedToEventArgs args)
+ {
+ base.OnNavigatedTo(args);
+
+ // Simulate the scenario: navigate back after 3 seconds
+ // This can cause a crash if the picker dialog is open
+ _ = Task.Run(async () =>
+ {
+ await Task.Delay(3000);
+ await Dispatcher.DispatchAsync(async () =>
+ {
+ await Navigation.PopToRootAsync();
+ });
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml
new file mode 100644
index 000000000000..529e9216fd18
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml.cs
new file mode 100644
index 000000000000..15e58696ae10
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue31889.xaml.cs
@@ -0,0 +1,26 @@
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, 31889, "Entry and Editor AppThemeBinding colors for text and placeholder reset to default on theme change", PlatformAffected.Android)]
+public partial class Issue31889 : ContentPage
+{
+ public Issue31889()
+ {
+ InitializeComponent();
+ this.SetAppThemeColor(BackgroundColorProperty, Colors.White, Colors.Black);
+ }
+ public void OnLightThemeButtonClicked(object sender, EventArgs e)
+ {
+ if (Application.Current is not null)
+ {
+ Application.Current.UserAppTheme = AppTheme.Light;
+ }
+ }
+
+ public void OnDarkThemeButtonClicked(object sender, EventArgs e)
+ {
+ if (Application.Current is not null)
+ {
+ Application.Current.UserAppTheme = AppTheme.Dark;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnDarkTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnDarkTheme.png
new file mode 100644
index 000000000000..10cee57dd09a
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnLightTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnLightTheme.png
new file mode 100644
index 000000000000..025421d6ddf4
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/CollectionViewSelectionModeOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..aa6d55a4221d
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..c0ef7977e3ac
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..202d7e909a5f
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..8ce83c15f1e4
Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18443.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18443.cs
index b8e2df035caa..d278c9ec0c7d 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18443.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18443.cs
@@ -21,7 +21,7 @@ public void EntrySelectionLengthRuntimeUpdate()
#endif
#if IOS
- VerifyScreenshot(cropBottom: 1080);
+ VerifyScreenshot(cropBottom: 1140);
#else
VerifyScreenshot();
#endif
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30868.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30868.cs
new file mode 100644
index 000000000000..cb58777e96fc
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30868.cs
@@ -0,0 +1,43 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue30868 : _IssuesUITest
+{
+ public Issue30868(TestDevice testDevice) : base(testDevice)
+ {
+ }
+ public override string Issue => "CollectionView selection visual states";
+
+#if TEST_FAILS_ON_WINDOWS // Using AppThemeBinding and changing theme not working on Windows
+ [Test, Order(1)]
+ [Category(UITestCategories.CollectionView)]
+ public void CollectionViewSelectionModeOnDarkTheme()
+ {
+ try
+ {
+ App.SetDarkTheme();
+ App.WaitForElement("Item 2");
+ App.Tap("Item 2");
+ VerifyScreenshot();
+ }
+ finally
+ {
+ App.SetLightTheme();
+ }
+ }
+#endif
+
+ [Test, Order(2)]
+ [Category(UITestCategories.CollectionView)]
+ public void CollectionViewSelectionModeOnLightTheme()
+ {
+ App.WaitForElement("Item 2");
+#if WINDOWS
+ App.Tap("Item 2");
+#endif
+ VerifyScreenshot();
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31372.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31372.cs
new file mode 100644
index 000000000000..52b44efda6c0
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31372.cs
@@ -0,0 +1,22 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue31372 : _IssuesUITest
+ {
+ public override string Issue => "IsPresented=true Not Working on Initial Value in FlyoutPage";
+
+ public Issue31372(TestDevice device)
+ : base(device)
+ { }
+
+ [Test]
+ [Category(UITestCategories.FlyoutPage)]
+ public void VerifyIsPresentedInitialValue()
+ {
+ App.WaitForElement("FlyoutLabel");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31731.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31731.cs
new file mode 100644
index 000000000000..ce1747520015
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31731.cs
@@ -0,0 +1,43 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue31731 : _IssuesUITest
+{
+ public Issue31731(TestDevice testDevice) : base(testDevice)
+ {
+ }
+
+ public override string Issue => "Picker dialog causes crash when page is popped while dialog is open";
+
+ [Test]
+ [Category(UITestCategories.Picker)]
+ public void PickerDialogDoesNotCrashWhenPagePoppedWhileDialogOpen()
+ {
+ // Wait for the main page to load
+ App.WaitForElement("statusLabel");
+ App.WaitForElement("navigateButton");
+
+ // Navigate to the picker page
+ App.Tap("navigateButton");
+
+ // Wait for picker page to load
+ App.WaitForElement("colorPicker");
+ App.WaitForElement("pageStatusLabel");
+
+ // Open the picker dialog
+ App.Tap("colorPicker");
+
+ // Wait for a moment to ensure dialog is open, then wait for auto navigation
+ // The page will automatically pop after 3 seconds
+ // If the bug exists, this would cause a crash
+ System.Threading.Thread.Sleep(4000); // Wait longer than the 3-second delay
+
+ // If we reach this point without crashing, the test passes
+ // Verify we're back on the main page
+ App.WaitForElement("statusLabel");
+ App.WaitForElement("navigateButton");
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31889.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31889.cs
new file mode 100644
index 000000000000..dbf090497320
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue31889.cs
@@ -0,0 +1,61 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue31889 : _IssuesUITest
+{
+ public Issue31889(TestDevice testDevice) : base(testDevice) { }
+
+ private const string TestEntryId = "TestEntry";
+ private const string TestEditorId = "TestEditor";
+ private const string DarkThemeButtonId = "DarkThemeButton";
+ private const string LightThemeButtonId = "LightThemeButton";
+ private const string DoneButtonId = "Done";
+ private const string TextColorDarkTheme = "EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme";
+ private const string TextColorLightTheme = "EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme";
+ private const string PlaceholderColorDarkTheme = "EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme";
+ private const string PlaceholderColorLightTheme = "EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme";
+ public override string Issue => "Entry and Editor AppThemeBinding colors for text and placeholder reset to default on theme change";
+
+ [Test, Order(1)]
+ [Category(UITestCategories.Entry)]
+ public void EntryAndEditorTextColorAppThemeBindingUpdatesOnThemeChange()
+ {
+ App.WaitForElement(TestEntryId);
+ App.WaitForElement(DarkThemeButtonId);
+ App.Tap(DarkThemeButtonId);
+ VerifyScreenshot(TextColorDarkTheme);
+ App.WaitForElement(LightThemeButtonId);
+ App.Tap(LightThemeButtonId);
+ VerifyScreenshot(TextColorLightTheme);
+ }
+
+ [Test, Order(2)]
+ [Category(UITestCategories.Entry)]
+ public void EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnThemeChange()
+ {
+ App.WaitForElement(TestEntryId);
+ App.ClearText(TestEntryId);
+
+ App.WaitForElement(TestEditorId);
+ App.ClearText(TestEditorId);
+#if MACCATALYST // On macOS, clearing the text in the Editor does not remove the full content.
+ App.ClearText(TestEditorId);
+#endif
+#if IOS
+ if (App.IsKeyboardShown())
+ {
+ App.WaitForElement(DoneButtonId);
+ App.Tap(DoneButtonId);
+ }
+#endif
+ App.WaitForElement(DarkThemeButtonId);
+ App.Tap(DarkThemeButtonId);
+ VerifyScreenshot(PlaceholderColorDarkTheme);
+ App.WaitForElement(LightThemeButtonId);
+ App.Tap(LightThemeButtonId);
+ VerifyScreenshot(PlaceholderColorLightTheme);
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewPreSelectionShouldUpdate.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewPreSelectionShouldUpdate.png
index 93e061e07594..f1c3c0e83eee 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewPreSelectionShouldUpdate.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewPreSelectionShouldUpdate.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewSelectionModeOnLightTheme.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewSelectionModeOnLightTheme.png
new file mode 100644
index 000000000000..3aca2b40a70e
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/CollectionViewSelectionModeOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..a4d66c8ef4e2
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..6e947797b2d3
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..5c252be3cdad
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..6c1f1362a4e4
Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/SelectedItemsShowSelected_multiple.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/SelectedItemsShowSelected_multiple.png
index a5042cb11c30..977942e44475 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/SelectedItemsShowSelected_multiple.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/SelectedItemsShowSelected_multiple.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsGroupedListWhenMultipleModePreSelection.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsGroupedListWhenMultipleModePreSelection.png
index 075627c54505..64efb133f03f 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsGroupedListWhenMultipleModePreSelection.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsGroupedListWhenMultipleModePreSelection.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsObservableCollectionWhenMultipleModePreSelection.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsObservableCollectionWhenMultipleModePreSelection.png
index 5c884a59c092..7bbd77a206f7 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsObservableCollectionWhenMultipleModePreSelection.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyModelItemsObservableCollectionWhenMultipleModePreSelection.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifySelectionModeMultipleWhenProgrammaticSelectionWorksWithVerticalList.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifySelectionModeMultipleWhenProgrammaticSelectionWorksWithVerticalList.png
index 521dd2dbd212..31d457ad6591 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifySelectionModeMultipleWhenProgrammaticSelectionWorksWithVerticalList.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifySelectionModeMultipleWhenProgrammaticSelectionWorksWithVerticalList.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsGroupedListWhenMultipleModePreSelection.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsGroupedListWhenMultipleModePreSelection.png
index cb6aef9c6ecc..18fb3670c886 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsGroupedListWhenMultipleModePreSelection.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsGroupedListWhenMultipleModePreSelection.png differ
diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsObservableCollectionWhenMultipleModePreSelection.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsObservableCollectionWhenMultipleModePreSelection.png
index 8b80e0e63f1b..60017dfb2989 100644
Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsObservableCollectionWhenMultipleModePreSelection.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/VerifyStringItemsObservableCollectionWhenMultipleModePreSelection.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnDarkTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnDarkTheme.png
new file mode 100644
index 000000000000..c89cdb353799
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnLightTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnLightTheme.png
new file mode 100644
index 000000000000..322c9dea8529
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/CollectionViewSelectionModeOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..a3cde224c923
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..2ba6066c8e37
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorPlaceholderTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png
new file mode 100644
index 000000000000..b6245a98a727
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnDarkTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png
new file mode 100644
index 000000000000..97ffd1296135
Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntryAndEditorTextColorAppThemeBindingUpdatesOnLightTheme.png differ
diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntrySelectionLengthRuntimeUpdate.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntrySelectionLengthRuntimeUpdate.png
index b1c60e7d1b5c..5ff9dfac24af 100644
Binary files a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntrySelectionLengthRuntimeUpdate.png and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/EntrySelectionLengthRuntimeUpdate.png differ
diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs
index aecaaf169b4e..731e511b3f37 100644
--- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs
+++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs
@@ -58,8 +58,7 @@ protected override void DisconnectHandler(MauiDatePicker platformView)
if (_dialog != null)
{
_dialog.DismissEvent -= OnDialogDismiss;
- _dialog.Hide();
- _dialog.Dispose();
+ _dialog.Dismiss();
_dialog = null;
}
diff --git a/src/Core/src/Handlers/FlyoutView/FlyoutViewHandler.Windows.cs b/src/Core/src/Handlers/FlyoutView/FlyoutViewHandler.Windows.cs
index 1165fd60c203..c6d7941d2c83 100644
--- a/src/Core/src/Handlers/FlyoutView/FlyoutViewHandler.Windows.cs
+++ b/src/Core/src/Handlers/FlyoutView/FlyoutViewHandler.Windows.cs
@@ -21,12 +21,25 @@ protected override void ConnectHandler(RootNavigationView platformView)
_navigationRootManager = MauiContext?.GetNavigationRootManager();
platformView.PaneOpened += OnPaneOpened;
platformView.PaneClosed += OnPaneClosed;
+ platformView.Loaded += OnLoaded;
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ // Unwire the event to ensure it only fires once
+ PlatformView.Loaded -= OnLoaded;
+
+ if (VirtualView is not null)
+ {
+ PlatformView.IsPaneOpen = VirtualView.IsPresented;
+ }
}
protected override void DisconnectHandler(RootNavigationView platformView)
{
platformView.PaneOpened -= OnPaneOpened;
platformView.PaneClosed -= OnPaneClosed;
+ platformView.Loaded -= OnLoaded;
}
void OnPaneOpened(NavigationView sender, object args)
diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Android.cs b/src/Core/src/Handlers/Picker/PickerHandler.Android.cs
index 342d1e439bcf..66a54812a6d0 100644
--- a/src/Core/src/Handlers/Picker/PickerHandler.Android.cs
+++ b/src/Core/src/Handlers/Picker/PickerHandler.Android.cs
@@ -29,6 +29,14 @@ protected override void DisconnectHandler(MauiPicker platformView)
{
platformView.Click -= OnClick;
+ if (_dialog != null)
+ {
+ _dialog.ShowEvent -= OnDialogShown;
+ _dialog.DismissEvent -= OnDialogDismiss;
+ _dialog.Dismiss();
+ _dialog = null;
+ }
+
base.DisconnectHandler(platformView);
}
diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs
index 83c0d141fa12..3cbf4126f033 100644
--- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs
+++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs
@@ -33,7 +33,7 @@ protected override void DisconnectHandler(MauiTimePicker platformView)
if (_dialog != null)
{
_dialog.DismissEvent -= OnDialogDismiss;
- _dialog.Hide();
+ _dialog.Dismiss();
_dialog = null;
}
diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs
index 5be958658882..55c51b78f57d 100644
--- a/src/Core/src/Platform/Android/EditTextExtensions.cs
+++ b/src/Core/src/Platform/Android/EditTextExtensions.cs
@@ -48,7 +48,7 @@ public static void UpdateTextColor(this EditText editText, Graphics.Color textCo
{
editText.SetTextColor(c);
}
- else
+ else if (textColor is null)
{
// Fallback to system default color
if (OperatingSystem.IsAndroidVersionAtLeast(23) && editText.Context?.Theme is Resources.Theme theme)
@@ -154,7 +154,7 @@ public static void UpdatePlaceholderColor(this EditText editText, Graphics.Color
{
if (placeholderTextColor is not null && PlatformInterop.CreateEditTextColorStateList(editText.HintTextColors, placeholderTextColor.ToPlatform()) is ColorStateList c)
editText.SetHintTextColor(c);
- else
+ else if (placeholderTextColor is null)
{
// Fallback to system default color
var typedValue = new TypedValue();
diff --git a/src/Graphics/src/Graphics/Graphics.csproj b/src/Graphics/src/Graphics/Graphics.csproj
index 621b0bc601e3..f4df82ab0627 100644
--- a/src/Graphics/src/Graphics/Graphics.csproj
+++ b/src/Graphics/src/Graphics/Graphics.csproj
@@ -38,6 +38,7 @@
+