Skip to content

Commit

Permalink
feat: Replace Page with correct type when reloaded
Browse files Browse the repository at this point in the history
Create an instance of the same type as the element being reloaded, and replace the old element in the visual tree rather than nesting inside of it.
  • Loading branch information
davidjohnoliver committed Dec 3, 2021
1 parent c26bd89 commit 64a25da
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Media;

namespace Uno.UI.RemoteControl.HotReload
{
Expand Down Expand Up @@ -39,11 +40,11 @@ private async Task ReloadFile(FileReload fileReload)
{
#if __IOS__
case UserControl userControl:
userControl.Content = XamlReader.Load(fileReload.Content) as UIKit.UIView;
userControl.Content = XamlReader.LoadUsingXClass(fileReload.Content) as UIKit.UIView;
break;
#endif
case ContentControl content:
content.Content = XamlReader.LoadUsingXClass(fileReload.Content);
SwapViews(content, XamlReader.LoadUsingXClass(fileReload.Content) as ContentControl);
break;
}
}
Expand Down Expand Up @@ -119,5 +120,32 @@ IEnumerable<IEnumerable<UIElement>> Dig()
}
}
}

private static void SwapViews(FrameworkElement oldView, FrameworkElement newView)
{
var parentAsContentControl = oldView.Parent as ContentControl;
parentAsContentControl = parentAsContentControl ?? (oldView.Parent as ContentPresenter)?.FindFirstParent<ContentControl>();

if (parentAsContentControl?.Content == oldView)
{
parentAsContentControl.Content = newView;
}
else
{
VisualTreeHelper.SwapViews(oldView, newView);
}

PropagateProperties(oldView, newView);
}

private static void PropagateProperties(FrameworkElement oldView, FrameworkElement newView)
{
newView.BaseUri = oldView.BaseUri;

if (oldView is Page oldPage && newView is Page newPage)
{
newPage.Frame = oldPage.Frame;
}
}
}
}
41 changes: 41 additions & 0 deletions src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using Android.Views;
using Uno.Extensions;
using Uno.UI;

namespace Windows.UI.Xaml.Media
{
public partial class VisualTreeHelper
{
internal static void SwapViews(UIElement oldView, UIElement newView)
{
var parentViewGroup = oldView?.Parent as ViewGroup;
var currentPosition = parentViewGroup?.GetChildren().IndexOf(oldView);

if (parentViewGroup != null && currentPosition != null && currentPosition.Value != -1)
{
parentViewGroup.RemoveViewAt(currentPosition.Value);

var unoViewGroup = parentViewGroup as UnoViewGroup;

if (unoViewGroup != null)
{
var newContentAsFrameworkElement = newView as IFrameworkElement;
if (newContentAsFrameworkElement != null)
{
newContentAsFrameworkElement.TemplatedParent = (unoViewGroup as IFrameworkElement)?.TemplatedParent;
}
unoViewGroup.AddView(newView, currentPosition.Value);
}
else
{
parentViewGroup.AddView(newView, currentPosition.Value);
}
}
}
}
}
28 changes: 28 additions & 0 deletions src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.iOSmacOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using Uno.Extensions;

namespace Windows.UI.Xaml.Media
{
public partial class VisualTreeHelper
{
internal static void SwapViews(UIElement oldView, UIElement newView)
{
var currentPosition = oldView?.Superview?.Subviews.IndexOf(oldView) ?? -1;

if (currentPosition != -1) {
var currentSuperview = oldView?.Superview;
oldView?.RemoveFromSuperview();

#if __IOS__
currentSuperview?.InsertSubview(newView, currentPosition);
#elif __MACOS__
currentSuperview.AddSubview(newView, NSWindowOrderingMode.Above, currentSuperview.Subviews[Math.Max(0, currentPosition-1)]);
#endif
}
}
}
}
27 changes: 27 additions & 0 deletions src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.netstd.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using Uno.Extensions;

namespace Windows.UI.Xaml.Media
{
public partial class VisualTreeHelper
{
internal static void SwapViews(UIElement oldView, UIElement newView)
{
if ((oldView as FrameworkElement)?.Parent is FrameworkElement parentElement)
{
var currentPosition = parentElement.GetChildren().IndexOf(oldView);

if (currentPosition != -1)
{
parentElement.RemoveChild(oldView);

parentElement.AddChild(newView, currentPosition);
}
}
}
}
}

0 comments on commit 64a25da

Please sign in to comment.