-
Notifications
You must be signed in to change notification settings - Fork 423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] Popup doesn't work with hot reload #620
Comments
Hey @drasticactions, in an overview can you tell if this is on us? |
I got a bit curious and looked at the .NET MAUI source code. Looks like classes have to implement The See also: |
@mavispuford IHotReloadabieView has nothing to do with XAML Hot Reload, it has to do with Comet. Implementing it won't do anything for XAML Hot Reload. @pictos For XAML Hot Reload to work, you need to implement IVisualTreeElement, https://github.com/dotnet/maui/blob/main/src/Core/src/Core/IVisualTreeElement.cs Most base MAUI controls (Apart from ListView) implement this out of the box. XAML Hot Reload checks if the control implements this and uses it to then go through the children. If your control doesn't implement this, it will not show up in the Live Visual Tree, and will then not be tracked at all for XAML Hot Reload. |
@drasticactions. Thanks for the answer, I'll look further to implement this. And all the views should implement this? |
It depends on the control, but generally you should only need to place it on the top most level, unless the control handles child elements in a weird way. Basically, if you don't see the child elements in the Live Visual Tree, it is not tracked and can't be hot reloaded. You may also need to make sure whenever the popup is invoked, that VisualDiagnostics OnVisualTree changes are fired, https://github.com/dotnet/maui/blob/main/src/Core/src/VisualDiagnostics/VisualDiagnostics.cs#L77-L80 |
Also, I would leave an issue in the MAUI repo about docs for this, since none of that is obvious unless you're me, lol. |
or if the person know that you know these secrets xP I'll find time to fill out an issue |
has any changes happened for this? |
@LennoxP90 not yet |
@drasticactions So, I'm trying to create a workaround and implement the Hot Reload support for my specific popup directly using your instructions...but I can't make it work. I tried to look inside the MAUI source code for other controls but I'm kinda lost....any advice or push in some direction would be greatly appreciated. public partial class MySpecificPopup : Popup, IVisualTreeElement
{
public PoiDetailPopup()
{
InitializeComponent();
VisualDiagnostics.OnChildAdded(Application.Current!.MainPage!, this);
}
IReadOnlyList<IVisualTreeElement> IVisualTreeElement.GetVisualChildren() => new List<IVisualTreeElement>() { this.Content! }.AsReadOnly();
IVisualTreeElement? IVisualTreeElement.GetVisualParent() => Application.Current!.MainPage!;
} |
https://github.com/dotnet/maui/pull/14006/files You can see this in this PR. You need to get your control into MAUIs visual tree, or else Hot Reload can't work since it's not visible to it. In your case, I don't know what the right approach is. I would guess that something needs to add |
I just want to clarify that I have the simplest use case, just simply showing the public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
this.ShowPopup(new MyPopup());
}
} Here I can see that the page is set as the Popup parent but I guess that does not translate directly into adding it to the Visual Tree. Not sure how that would work ....I thought that ContentPage can have a single child only. |
This circles back to what we've been chatting about. Currently adding I worked with @pictos a little bit to try and hack it together but we weren't super successful. |
Now that LogicalChildren APIs are in MAUI .NET8, calling addlogicalchildren should make this work. But as that's a .NET8 only API, it'll need a .NET8 version of the communitytoolkit, which we don't yet have. So that's the next step, I believe, for this issue - multitargeting to .NET8. |
While I wouldn't normally suggest this approach, given .NET 7 is not really going to change anything in this area of the code, it is probably safe enough to use some reflection if you really want to multitarget this support. Here's what I used in Maui.VirtualListView before the methods were added in .NET 8: internal static class LogicalChildrenHelpers
{
static MethodInfo removeLogicalChildMethod = null;
internal static void RemoveLogicalChild(this Element parent, IView view)
{
if (view is Element elem)
{
removeLogicalChildMethod ??= GetLogicalChildMethod(parent, "RemoveLogicalChildInternal", "RemoveLogicalChild");
removeLogicalChildMethod?.Invoke(parent, new[] { elem });
}
}
static MethodInfo addLogicalChildMethod = null;
internal static void AddLogicalChild(this Element parent, IView view)
{
if (view is Element elem)
{
addLogicalChildMethod ??= GetLogicalChildMethod(parent, "AddLogicalChildInternal", "AddLogicalChild");
addLogicalChildMethod?.Invoke(parent, new[] { elem });
}
}
static MethodInfo GetLogicalChildMethod(Element parent, string internalName, string publicName)
{
var internalMethod = parent.GetType().GetMethod(
internalName,
BindingFlags.Instance | BindingFlags.NonPublic,
new[] { typeof(Element) });
if (internalMethod is null)
{
internalMethod = parent.GetType().GetMethod(
publicName,
BindingFlags.Instance | BindingFlags.Public,
new[] { typeof(Element) });
}
return internalMethod;
}
} |
Call AddLogicalChild/RemoveLogicalChild when the popup is shown/closed so that popups are included in the logical (and visual) tree, so that Hot Reload works for them. The Live Visual Tree VS UI now shows popup content as well. Fixes CommunityToolkit#620 As Shane explained to me, the rule as of MAUI in .NET8 is that whenenever Parent is set on an Element, AddLogicalChild should also be called to include the element in the logical children. RemoveLogicalChild should be called when the Parent is set to null. This may be more automatic in .NET9, but for .NET8 that's what's needed so that the logical tree is kept up to date.
This was a good tip. But as the CommunityToolkit no longer supports .NET7 (something I've since learned), my fix PR #1635 just calls the newly exposed .NET8 APIs directly, keeping things simple. |
* Fix Hot Reload with Popup Call AddLogicalChild/RemoveLogicalChild when the popup is shown/closed so that popups are included in the logical (and visual) tree, so that Hot Reload works for them. The Live Visual Tree VS UI now shows popup content as well. Fixes #620 As Shane explained to me, the rule as of MAUI in .NET8 is that whenenever Parent is set on an Element, AddLogicalChild should also be called to include the element in the logical children. RemoveLogicalChild should be called when the Parent is set to null. This may be more automatic in .NET9, but for .NET8 that's what's needed so that the logical tree is kept up to date. * Remove setting the Parent as that's not needed Shane pointed out that Add/RemoveLogicalChild also updates the parent, so there's no need for our code to do that as well. * Protect against NREs for all calls to AddLogicalChild --------- Co-authored-by: Brandon Minnick <[email protected]> Co-authored-by: Pedro Jesus <[email protected]>
Is there an existing issue for this?
Current Behavior
Popup
xaml changes aren't reflected with hot reload. I'm not sure if this was part of the original intended functionality, but it can be quite tedious to iterate onPopup
design changes.Expected Behavior
Popup
xaml changes should ideally be reflected during runtime, just like other Views in .NET MAUI.Steps To Reproduce
Link to public reproduction project repository
https://github.com/mavispuford/PopupHotReloadNotWorking
Environment
Anything else?
I've also reproduced this bug in Android. I haven't tested platforms outside of Windows/Android.
The text was updated successfully, but these errors were encountered: