diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml
new file mode 100644
index 000000000000..878334a64cac
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml.cs
new file mode 100644
index 000000000000..876dbfa5113a
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml.cs
@@ -0,0 +1,13 @@
+using Microsoft.Maui.Controls;
+
+namespace Maui.Controls.Sample.Issues
+{
+ [Issue(IssueTracker.Github, 30403, "Image under WinUI does not respect VerticalOptions and HorizontalOptions", PlatformAffected.UWP)]
+ public partial class Issue30403 : ContentPage
+ {
+ public Issue30403()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30403.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30403.cs
new file mode 100644
index 000000000000..477737906520
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30403.cs
@@ -0,0 +1,32 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue30403 : _IssuesUITest
+ {
+ public Issue30403(TestDevice device)
+ : base(device)
+ { }
+
+ public override string Issue => "Image under WinUI does not respect VerticalOptions and HorizontalOptions";
+
+ [Test]
+ [Category(UITestCategories.Layout)]
+ [Category(UITestCategories.Image)]
+ public void ImageShouldRespectLayoutOptions()
+ {
+ // Wait for images to load
+ App.WaitForElement("CenteredImage");
+ App.WaitForElement("StartImage");
+ App.WaitForElement("EndImage");
+ App.WaitForElement("FillImage");
+ App.WaitForElement("WideImage");
+
+ // On Windows, images should be positioned according to their alignment options
+ // instead of stretching to fill the container
+ VerifyScreenshot();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Core/src/Handlers/Image/ImageHandler.Windows.cs b/src/Core/src/Handlers/Image/ImageHandler.Windows.cs
index ee3a6ddbd533..a939371f402c 100644
--- a/src/Core/src/Handlers/Image/ImageHandler.Windows.cs
+++ b/src/Core/src/Handlers/Image/ImageHandler.Windows.cs
@@ -44,6 +44,8 @@ protected override void SetupContainer()
UpdateValue(nameof(IView.Height));
UpdateValue(nameof(IView.Width));
+ UpdateValue(nameof(IView.HorizontalLayoutAlignment));
+ UpdateValue(nameof(IView.VerticalLayoutAlignment));
}
///
@@ -138,6 +140,42 @@ public static void MapSource(IImageHandler handler, IImage image) =>
public static Task MapSourceAsync(IImageHandler handler, IImage image) =>
handler.SourceLoader.UpdateImageSourceAsync();
+ ///
+ /// Maps the abstract property to the platform-specific implementations.
+ ///
+ /// The associated handler.
+ /// The associated instance.
+ internal static void MapHorizontalLayoutAlignment(IImageHandler handler, IImage image)
+ {
+ // Apply alignment to container if it exists, otherwise to the platform view
+ if (handler.ContainerView is FrameworkElement container)
+ {
+ container.UpdateHorizontalLayoutAlignment(image);
+ }
+ else
+ {
+ handler.PlatformView?.UpdateHorizontalLayoutAlignment(image);
+ }
+ }
+
+ ///
+ /// Maps the abstract property to the platform-specific implementations.
+ ///
+ /// The associated handler.
+ /// The associated instance.
+ internal static void MapVerticalLayoutAlignment(IImageHandler handler, IImage image)
+ {
+ // Apply alignment to container if it exists, otherwise to the platform view
+ if (handler.ContainerView is FrameworkElement container)
+ {
+ container.UpdateVerticalLayoutAlignment(image);
+ }
+ else
+ {
+ handler.PlatformView?.UpdateVerticalLayoutAlignment(image);
+ }
+ }
+
void OnImageOpened(object sender, RoutedEventArgs e)
{
// Because this resolves from a task we should validate that the
diff --git a/src/Core/src/Handlers/Image/ImageHandler.cs b/src/Core/src/Handlers/Image/ImageHandler.cs
index cfcc20d83514..47fc788f1bbf 100644
--- a/src/Core/src/Handlers/Image/ImageHandler.cs
+++ b/src/Core/src/Handlers/Image/ImageHandler.cs
@@ -24,6 +24,8 @@ public partial class ImageHandler : IImageHandler
#if WINDOWS
[nameof(IImage.Height)] = MapHeight,
[nameof(IImage.Width)] = MapWidth,
+ [nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
+ [nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
#endif
[nameof(IImage.Aspect)] = MapAspect,
[nameof(IImage.IsAnimationPlaying)] = MapIsAnimationPlaying,
diff --git a/src/Core/src/Platform/Windows/ImageViewExtensions.cs b/src/Core/src/Platform/Windows/ImageViewExtensions.cs
index fbcd994371c5..80e7280e3981 100644
--- a/src/Core/src/Platform/Windows/ImageViewExtensions.cs
+++ b/src/Core/src/Platform/Windows/ImageViewExtensions.cs
@@ -16,11 +16,45 @@ public static void UpdateAspect(this WImage imageView, IImage image)
{
imageView.Stretch = image.Aspect.ToStretch();
+ // For AspectFill, we still want center alignment on the image itself
+ // but for other aspects, the layout alignment should be controlled by
+ // the container or the layout alignment properties
if (image.Aspect == Aspect.AspectFill)
{
imageView.VerticalAlignment = VerticalAlignment.Center;
imageView.HorizontalAlignment = HorizontalAlignment.Center;
}
+ else
+ {
+ // Clear any previous alignment settings when not AspectFill
+ // The layout alignment will be handled by the container or layout alignment properties
+ imageView.ClearValue(FrameworkElement.VerticalAlignmentProperty);
+ imageView.ClearValue(FrameworkElement.HorizontalAlignmentProperty);
+ }
+ }
+
+ public static void UpdateHorizontalLayoutAlignment(this FrameworkElement platformView, IView view)
+ {
+ platformView.HorizontalAlignment = view.HorizontalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => HorizontalAlignment.Left,
+ Primitives.LayoutAlignment.Center => HorizontalAlignment.Center,
+ Primitives.LayoutAlignment.End => HorizontalAlignment.Right,
+ Primitives.LayoutAlignment.Fill => HorizontalAlignment.Stretch,
+ _ => HorizontalAlignment.Stretch
+ };
+ }
+
+ public static void UpdateVerticalLayoutAlignment(this FrameworkElement platformView, IView view)
+ {
+ platformView.VerticalAlignment = view.VerticalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => VerticalAlignment.Top,
+ Primitives.LayoutAlignment.Center => VerticalAlignment.Center,
+ Primitives.LayoutAlignment.End => VerticalAlignment.Bottom,
+ Primitives.LayoutAlignment.Fill => VerticalAlignment.Stretch,
+ _ => VerticalAlignment.Stretch
+ };
}
public static void UpdateIsAnimationPlaying(this WImage imageView, IImageSourcePart image)