From 4b2df2795d7565c9e5d4dcf5e8c6c0950b1fd20a Mon Sep 17 00:00:00 2001 From: Andres Pineda Date: Fri, 25 Oct 2024 11:55:08 -0400 Subject: [PATCH 1/4] test: PersonPicture add manual test --- .../UITests.Shared/UITests.Shared.projitems | 7 ++++ .../PersonPictureLateBindingPage.xaml | 27 ++++++++++++++ .../PersonPictureLateBindingPage.xaml.cs | 37 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml create mode 100644 src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems index df5919797d12..5c74fc29c94d 100644 --- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems +++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems @@ -2374,6 +2374,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -7163,6 +7167,9 @@ PersonPicturePage.xaml + + PersonPictureLateBindingPage.xaml + Pivot_CustomContent_Automated.xaml diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml new file mode 100644 index 000000000000..f9cabbb1bb51 --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs new file mode 100644 index 000000000000..6f0b4cbc36c0 --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.ObjectModel; +using MUXControlsTestApp.Utilities; +using Uno.UI.Samples.Controls; +using Windows.ApplicationModel.Contacts; +using System.Threading.Tasks; + +namespace MUXControlsTestApp +{ + [SampleControlInfo( + "MUX", + "PersonPictureLateBinding", + isManualTest: true)] +#pragma warning disable UXAML0002 // does not explicitly define the Microsoft.UI.Xaml.Controls.UserControl base type in code behind. + public sealed partial class PersonPictureLateBindingPage +#pragma warning restore UXAML0002 // does not explicitly define the Microsoft.UI.Xaml.Controls.UserControl base type in code behind. + { + public string ImagePath { get; } = "ms-appx:///Assets/ingredient2.png"; + + public string LeName { get; } = "James Bondi"; + + public PersonPictureLateBindingPage() + { + this.InitializeComponent(); + _ = SetImagePathWithDelay(); + } + + private async Task SetImagePathWithDelay() + { + await Task.Delay(1000); + DataContext = this; + } + } +} From 6944ff1f63711a25f582cbdf6408a5d7c56bde82 Mon Sep 17 00:00:00 2001 From: Andres Pineda Date: Fri, 25 Oct 2024 12:00:01 -0400 Subject: [PATCH 2/4] fix(iOS): PersonPicture late binding --- .../Controls/PersonPicture/PersonPicture.cs | 44 +++++++++++++++---- .../UI/Xaml/Media/ImageSource.crossruntime.cs | 6 --- src/Uno.UI/UI/Xaml/Media/ImageSource.cs | 5 +++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PersonPicture/PersonPicture.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PersonPicture/PersonPicture.cs index 0d7fd206d9d0..9fd98701201b 100644 --- a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PersonPicture/PersonPicture.cs +++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PersonPicture/PersonPicture.cs @@ -203,23 +203,33 @@ void UpdateIfReady() var templateSettings = TemplateSettings; templateSettings.ActualInitials = initials; - if (imageSrc != null) + + if (imageSrc is not null) { - var imageBrush = templateSettings.ActualImageBrush; - if (imageBrush == null) + if (templateSettings.ActualImageBrush is ImageBrush imageBrush) { - imageBrush = new ImageBrush(); - imageBrush.Stretch = Stretch.UniformToFill; - templateSettings.ActualImageBrush = imageBrush; + imageBrush.ImageSource = imageSrc; + } + else + { + templateSettings.ActualImageBrush = new ImageBrush() + { + ImageSource = imageSrc, + Stretch = Stretch.UniformToFill + }; } - - imageBrush.ImageSource = imageSrc; } else { templateSettings.ActualImageBrush = null; } +#if __IOS__ + if (templateSettings.ActualImageBrush is ImageBrush brush) + { + brush.ImageOpened += RefreshPhoto; + } +#endif // If the control is converted to 'Group-mode', we'll clear individual-specific information. // When IsGroup evaluates to false, we will restore state. if (IsGroup) @@ -228,7 +238,11 @@ void UpdateIfReady() } else { - if (imageSrc != null) + if (imageSrc is not null +#if __IOS__ + && imageSrc.IsOpened +#endif + ) { VisualStateManager.GoToState(this, "Photo", false); } @@ -245,6 +259,18 @@ void UpdateIfReady() UpdateAutomationName(); } +#if __IOS__ + void RefreshPhoto(object sender, RoutedEventArgs e) + { + VisualStateManager.GoToState(this, "Photo", false); + + if (TemplateSettings.ActualImageBrush is { } brush) + { + brush.ImageOpened -= RefreshPhoto; + } + } +#endif + void UpdateBadge() { if (BadgeImageSource != null) diff --git a/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs b/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs index 8b414d4196f7..38c3f2be6431 100644 --- a/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs +++ b/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs @@ -77,12 +77,6 @@ internal IDisposable Subscribe(Action onSourceOpened) return Disposable.Create(() => _subscriptions.Remove(onSourceOpened)); } - /// - /// Indicates that this source has already been opened - /// (So the onSourceOpened callback of Subscribe will be invoked synchronously!) - /// - internal bool IsOpened => _imageData.HasData; - private protected void InvalidateSource() { _imageData = default; diff --git a/src/Uno.UI/UI/Xaml/Media/ImageSource.cs b/src/Uno.UI/UI/Xaml/Media/ImageSource.cs index 95c87ebc4af7..a0ffa473ea5e 100644 --- a/src/Uno.UI/UI/Xaml/Media/ImageSource.cs +++ b/src/Uno.UI/UI/Xaml/Media/ImageSource.cs @@ -202,6 +202,11 @@ private set } } + /// + /// Indicates that this source has already been opened + /// (So the onSourceOpened callback of Subscribe will be invoked synchronously!) + /// + internal bool IsOpened => _imageData.HasData; partial void SetImageLoader(); internal void UnloadImageData() From 829456eee160965ba2e18ddf517cd0257585ce00 Mon Sep 17 00:00:00 2001 From: Andres Pineda Date: Fri, 25 Oct 2024 14:15:59 -0400 Subject: [PATCH 3/4] test: add manual test description --- .../PersonPictureTests/PersonPictureLateBindingPage.xaml.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs index 6f0b4cbc36c0..cccf100a02d5 100644 --- a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/PersonPictureTests/PersonPictureLateBindingPage.xaml.cs @@ -13,6 +13,9 @@ namespace MUXControlsTestApp [SampleControlInfo( "MUX", "PersonPictureLateBinding", + description: "Shows a PersonPicture control and a Textblock with a name. \n" + + "The PersonPicture control image is set after 1 second delay. \n" + + "The image should be displayed after the delay.", isManualTest: true)] #pragma warning disable UXAML0002 // does not explicitly define the Microsoft.UI.Xaml.Controls.UserControl base type in code behind. public sealed partial class PersonPictureLateBindingPage From 0cd2e49089de9630a697ef02e140f78fba9db1f9 Mon Sep 17 00:00:00 2001 From: Andres Pineda Date: Fri, 25 Oct 2024 18:07:36 -0400 Subject: [PATCH 4/4] chore: move property definition --- src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs | 6 ++++++ src/Uno.UI/UI/Xaml/Media/ImageSource.cs | 5 ----- src/Uno.UI/UI/Xaml/Media/ImageSource.iOS.cs | 5 +++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs b/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs index 38c3f2be6431..8b414d4196f7 100644 --- a/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs +++ b/src/Uno.UI/UI/Xaml/Media/ImageSource.crossruntime.cs @@ -77,6 +77,12 @@ internal IDisposable Subscribe(Action onSourceOpened) return Disposable.Create(() => _subscriptions.Remove(onSourceOpened)); } + /// + /// Indicates that this source has already been opened + /// (So the onSourceOpened callback of Subscribe will be invoked synchronously!) + /// + internal bool IsOpened => _imageData.HasData; + private protected void InvalidateSource() { _imageData = default; diff --git a/src/Uno.UI/UI/Xaml/Media/ImageSource.cs b/src/Uno.UI/UI/Xaml/Media/ImageSource.cs index a0ffa473ea5e..95c87ebc4af7 100644 --- a/src/Uno.UI/UI/Xaml/Media/ImageSource.cs +++ b/src/Uno.UI/UI/Xaml/Media/ImageSource.cs @@ -202,11 +202,6 @@ private set } } - /// - /// Indicates that this source has already been opened - /// (So the onSourceOpened callback of Subscribe will be invoked synchronously!) - /// - internal bool IsOpened => _imageData.HasData; partial void SetImageLoader(); internal void UnloadImageData() diff --git a/src/Uno.UI/UI/Xaml/Media/ImageSource.iOS.cs b/src/Uno.UI/UI/Xaml/Media/ImageSource.iOS.cs index 31926877edaf..a94258af0251 100644 --- a/src/Uno.UI/UI/Xaml/Media/ImageSource.iOS.cs +++ b/src/Uno.UI/UI/Xaml/Media/ImageSource.iOS.cs @@ -55,6 +55,11 @@ public static NSUrlSession DefaultSession static public implicit operator ImageSource(UIImage image) => new ImageSource(image); + /// + /// Indicates that this source has already been opened (So TryOpenSync will return true!) + /// + internal bool IsOpened => _imageData.HasData; + private static UIImage? OpenBundleFromString(string? bundle) { if (!bundle.IsNullOrWhiteSpace())