Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Maui.Controls.Sample.Issues.Issue30403"
Title="Issue30403">
<Grid RowDefinitions="*,*,*" ColumnDefinitions="*,*" Padding="20" BackgroundColor="LightGray">

<!-- Test Image with AspectFit and Center alignment -->
<Border Grid.Row="0" Grid.Column="0"
Stroke="Red" StrokeThickness="2"
HeightRequest="200" WidthRequest="200"
HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="dotnet_bot.png"
Aspect="AspectFit"
VerticalOptions="Center"
HorizontalOptions="Center"
AutomationId="CenteredImage" />
</Border>

<!-- Test Image with AspectFit and Start alignment -->
<Border Grid.Row="0" Grid.Column="1"
Stroke="Blue" StrokeThickness="2"
HeightRequest="200" WidthRequest="200"
HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="dotnet_bot.png"
Aspect="AspectFit"
VerticalOptions="Start"
HorizontalOptions="Start"
AutomationId="StartImage" />
</Border>

<!-- Test Image with AspectFit and End alignment -->
<Border Grid.Row="1" Grid.Column="0"
Stroke="Green" StrokeThickness="2"
HeightRequest="200" WidthRequest="200"
HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="dotnet_bot.png"
Aspect="AspectFit"
VerticalOptions="End"
HorizontalOptions="End"
AutomationId="EndImage" />
</Border>

<!-- Test Image with AspectFit and Fill alignment (should stretch) -->
<Border Grid.Row="1" Grid.Column="1"
Stroke="Orange" StrokeThickness="2"
HeightRequest="200" WidthRequest="200"
HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="dotnet_bot.png"
Aspect="AspectFit"
VerticalOptions="Fill"
HorizontalOptions="Fill"
AutomationId="FillImage" />
</Border>

<!-- Test with different aspect ratios -->
<Border Grid.Row="2" Grid.ColumnSpan="2"
Stroke="Purple" StrokeThickness="2"
HeightRequest="150" WidthRequest="400"
HorizontalOptions="Center" VerticalOptions="Center">
<Image Source="dotnet_bot.png"
Aspect="AspectFit"
VerticalOptions="Center"
HorizontalOptions="Center"
AutomationId="WideImage" />
</Border>

</Grid>
</ContentPage>
13 changes: 13 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30403.xaml.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
38 changes: 38 additions & 0 deletions src/Core/src/Handlers/Image/ImageHandler.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ protected override void SetupContainer()

UpdateValue(nameof(IView.Height));
UpdateValue(nameof(IView.Width));
UpdateValue(nameof(IView.HorizontalLayoutAlignment));
UpdateValue(nameof(IView.VerticalLayoutAlignment));
}

/// <inheritdoc/>
Expand Down Expand Up @@ -138,6 +140,42 @@ public static void MapSource(IImageHandler handler, IImage image) =>
public static Task MapSourceAsync(IImageHandler handler, IImage image) =>
handler.SourceLoader.UpdateImageSourceAsync();

/// <summary>
/// Maps the abstract <see cref="IView.HorizontalLayoutAlignment"/> property to the platform-specific implementations.
/// </summary>
/// <param name="handler">The associated handler.</param>
/// <param name="image">The associated <see cref="Image"/> instance.</param>
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);
}
}

/// <summary>
/// Maps the abstract <see cref="IView.VerticalLayoutAlignment"/> property to the platform-specific implementations.
/// </summary>
/// <param name="handler">The associated handler.</param>
/// <param name="image">The associated <see cref="Image"/> instance.</param>
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
Expand Down
2 changes: 2 additions & 0 deletions src/Core/src/Handlers/Image/ImageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
34 changes: 34 additions & 0 deletions src/Core/src/Platform/Windows/ImageViewExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading