From 4241bd48e724f1bf9313fc0f4f391b38963e12b7 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Mon, 24 Jun 2024 13:36:50 -0500 Subject: [PATCH] Wire RefreshView up to our xplat layout workflow (#23169) (#23218) * Use better layout/measure path with refreshview * - fix naming * - set RefreshView content to maui compatible container * - add test * - fix null operator * Update Issue23029.xaml.cs * - fix content panel so it removes previous content * - add additional check --- .../Elements/RefreshView/RefreshViewTests.cs | 177 ++---------------- .../Tests/Issues/Issue23029.cs | 22 +++ .../tests/TestCases/Issues/Issue23029.xaml | 45 +++++ .../tests/TestCases/Issues/Issue23029.xaml.cs | 54 ++++++ .../RefreshView/RefreshViewHandler.Windows.cs | 32 +++- .../RefreshView/RefreshViewHandler.iOS.cs | 32 +++- src/Core/src/Platform/Windows/ContentPanel.cs | 34 ++-- src/Core/src/Platform/iOS/MauiRefreshView.cs | 33 +--- .../PublicAPI/net-ios/PublicAPI.Unshipped.txt | 4 +- .../net-maccatalyst/PublicAPI.Unshipped.txt | 4 +- 10 files changed, 224 insertions(+), 213 deletions(-) create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23029.cs create mode 100644 src/Controls/tests/TestCases/Issues/Issue23029.xaml create mode 100644 src/Controls/tests/TestCases/Issues/Issue23029.xaml.cs diff --git a/src/Controls/tests/DeviceTests/Elements/RefreshView/RefreshViewTests.cs b/src/Controls/tests/DeviceTests/Elements/RefreshView/RefreshViewTests.cs index ee9dedbe9541..a5120677c4f3 100644 --- a/src/Controls/tests/DeviceTests/Elements/RefreshView/RefreshViewTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/RefreshView/RefreshViewTests.cs @@ -8,6 +8,7 @@ using Microsoft.Maui.Controls.Handlers.Items; using Microsoft.Maui.Handlers; using Microsoft.Maui.Hosting; +using Microsoft.Maui.Platform; using Xunit; namespace Microsoft.Maui.DeviceTests @@ -22,167 +23,29 @@ void SetupBuilder() builder.ConfigureMauiHandlers(handlers => { handlers.AddHandler(); + handlers.AddHandler(); + handlers.AddHandler(); }); }); } + [Fact(DisplayName = "Setting the content of RefreshView removes previous platform view from visual tree")] + public async Task ChangingRefreshViewContentRemovesPreviousContentsPlatformViewFromVisualTree() + { + SetupBuilder(); + var refreshView = new RefreshView(); + var initialContent = new Label(); + refreshView.Content = initialContent; - // [Fact(DisplayName = "IsRefreshing binding works")] - // public async Task IsRefreshingBindingWorks() - // { - // SetupBuilder(); - - // var vm = new RefreshPageViewModel(); - // var refreshView = new RefreshView() { BindingContext = vm }; - - // refreshView.SetBinding(RefreshView.IsRefreshingProperty, nameof(vm.IsRefreshing), BindingMode.TwoWay); - - // await CreateHandlerAndAddToWindow(refreshView, async handler => - // { - // var platformControl = handler.PlatformView; - // Assert.NotNull(platformControl); - // bool? platformIsRefreshing = null; - // #if WINDOWS - // Deferral refreshCompletionDeferral = null; - // platformControl.RefreshRequested += (s, e) => - // { - // refreshCompletionDeferral = e.GetDeferral(); - // platformIsRefreshing = true; - // }; - // #endif - // vm.IsRefreshing = true; - // #if ANDROID - // platformIsRefreshing = platformControl.Refreshing; - // #elif IOS - // platformIsRefreshing = platformControl.IsRefreshing; - // #elif WINDOWS - - // #endif - // Assert.NotNull(platformIsRefreshing); - // Assert.Equal(vm.IsRefreshing, platformIsRefreshing); - // await Task.Delay(300); - // vm.IsRefreshing = false; - // #if ANDROID - // platformIsRefreshing = platformControl.Refreshing; - // #elif IOS - // platformIsRefreshing = platformControl.IsRefreshing; - // #elif WINDOWS - // if(refreshCompletionDeferral != null) - // { - // refreshCompletionDeferral.Complete(); - // refreshCompletionDeferral = null; - // platformIsRefreshing = false; - // } - // #endif - // Assert.Equal(vm.IsRefreshing, platformIsRefreshing); - // await Task.Delay(1000); - // }); - // } - - // [Fact(DisplayName = "IsRefreshing binding works when started on platform")] - // public async Task IsRefreshingBindingWorksFromPlatform() - // { - // SetupBuilder(); - - // var vm = new RefreshPageViewModel(); - // var refreshView = new RefreshView() { BindingContext = vm }; - - // refreshView.SetBinding(RefreshView.IsRefreshingProperty, nameof(vm.IsRefreshing), BindingMode.TwoWay); - - // await CreateHandlerAndAddToWindow(refreshView, async handler => - // { - // var platformControl = handler.PlatformView; - // Assert.NotNull(platformControl); - // bool? platformIsRefreshing = null; - // #if WINDOWS - // Deferral refreshCompletionDeferral = null; - // platformControl.RefreshRequested += (s, e) => - // { - // refreshCompletionDeferral = e.GetDeferral(); - // platformIsRefreshing = true; - // }; - // platformControl.RequestRefresh(); - // #endif - - // #if ANDROID - // platformIsRefreshing = platformControl.Refreshing = true; - // #elif IOS - // platformIsRefreshing = platformControl.IsRefreshing = true; - // #elif WINDOWS - - // #endif - // Assert.NotNull(platformIsRefreshing); - // Assert.Equal(platformIsRefreshing, vm.IsRefreshing); - // await Task.Delay(300); - // vm.IsRefreshing = false; - // #if ANDROID - // platformIsRefreshing = platformControl.Refreshing; - // #elif IOS - // platformIsRefreshing = platformControl.IsRefreshing; - // #elif WINDOWS - // if (refreshCompletionDeferral != null) - // { - // refreshCompletionDeferral.Complete(); - // refreshCompletionDeferral = null; - // platformIsRefreshing = false; - // } - // #endif - // Assert.Equal(vm.IsRefreshing, platformIsRefreshing); - // await Task.Delay(1000); - // }); - // } - - // class RefreshPageViewModel : BaseViewModel - // { - // public RefreshPageViewModel() - // { - // Data = new ObservableCollection() - // { - // "Item 1", - // "Item 2", - // "Item 3" - // }; - // } - // bool _isRefreshing; - // ObservableCollection _data; - - // public bool IsRefreshing - // { - // get => _isRefreshing; - // set => SetProperty(ref _isRefreshing, value); - // } - - // public ObservableCollection Data - // { - // get => _data; - // set => SetProperty(ref _data, value); - // } - // } - - // public abstract class BaseViewModel : INotifyPropertyChanged - // { - // protected bool SetProperty(ref T backingStore, T value, - // [CallerMemberName] string propertyName = "", - // Action onChanged = null) - // { - // if (EqualityComparer.Default.Equals(backingStore, value)) - // return false; - - // backingStore = value; - // onChanged?.Invoke(); - // OnPropertyChanged(propertyName); - // return true; - // } - - // #region INotifyPropertyChanged - - // public event PropertyChangedEventHandler PropertyChanged; - // protected void OnPropertyChanged([CallerMemberName] string propertyName = "") - // { - // PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - // } - - // #endregion - // } + await AttachAndRun(refreshView, async (handler) => + { + var newContent = new Entry(); + Assert.NotNull(((initialContent as IView).Handler as IPlatformViewHandler).PlatformView.GetParent()); + refreshView.Content = newContent; + Assert.Null(((initialContent as IView).Handler as IPlatformViewHandler).PlatformView.GetParent()); + await Task.Yield(); + Assert.NotNull(((newContent as IView).Handler as IPlatformViewHandler).PlatformView.GetParent()); + }); + } } } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23029.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23029.cs new file mode 100644 index 000000000000..d6ce1df4bd0f --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue23029.cs @@ -0,0 +1,22 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class Issue23029 : _IssuesUITest + { + public override string Issue => "RefreshView doesn't use correct layout mechanisms"; + + public Issue23029(TestDevice device) : base(device) + { + } + + [Test] + [Category(UITestCategories.RefreshView)] + public void ValidateRefreshViewContentGetsFrameSet() + { + App.WaitForElement("SizeChangedLabel"); + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Issues/Issue23029.xaml b/src/Controls/tests/TestCases/Issues/Issue23029.xaml new file mode 100644 index 000000000000..956350fbc3b3 --- /dev/null +++ b/src/Controls/tests/TestCases/Issues/Issue23029.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + +