Skip to content
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

WebView2 html select dropdown positioning not updated #2290

Open
ispysoftware opened this issue Mar 21, 2022 · 46 comments
Open

WebView2 html select dropdown positioning not updated #2290

ispysoftware opened this issue Mar 21, 2022 · 46 comments
Assignees
Labels
bug Something isn't working tracked We are tracking this work internally.

Comments

@ispysoftware
Copy link

ispysoftware commented Mar 21, 2022

Description
Drop-downs don't update their location when the application window is moved. Their location is updated when the application window is resized.

Version
SDK: 1.0.1
Framework: .Net 5.0, WinUI
OS: Win 11

Repro Steps
Start an application containing a WebView2 instance, trigger a drop-down. Move the application window, trigger dropdown again - dropdown shows in original location.

winuibug

Additional context

AB#38615382

@ispysoftware ispysoftware added the bug Something isn't working label Mar 21, 2022
@ispysoftware ispysoftware changed the title html select dropdown positioning WebView2 html select dropdown positioning not updated Mar 21, 2022
@champnic champnic added the tracked We are tracking this work internally. label Mar 21, 2022
@champnic
Copy link
Member

Thanks for the bug report @ispysoftware, and sorry you're running into this. I've opened it on our backlog. Are you using WinUI 2 or WinUI 3 (through WindowsAppSDK)?

@ispysoftware
Copy link
Author

@champnic WinUI3

@ispysoftware
Copy link
Author

@champnic any update on this.. been over 2 months..

@champnic
Copy link
Member

champnic commented Jun 3, 2022

This is a bug on the WinUI control, and it looks like that team has begun work on a fix.

@ispysoftware
Copy link
Author

@champnic any chance you could chase this up - it's been holding us back since last year

@TomOeser
Copy link

@ispysoftware any news on that so you closed the issue?

I ran into the same issue with my WPF-App. Showing the dropdown right while in debug/release running from Visual Studio. As soon as i try to use it "from the outside" by starting the program in the output folders directly the dropdowns go off!

@ispysoftware ispysoftware reopened this Aug 24, 2022
@ispysoftware
Copy link
Author

@TomOeser no, sorry, i think i just clicked the wrong button by accident

@Eilon
Copy link

Eilon commented Sep 21, 2022

Thanks to Mike from the Windows App SDK team, we came up with a workaround for anyone running into this issue. The same type of workaround should work in a Windows App SDK (WinUI3) app, and also in a .NET MAUI app running on Windows.

The workaround is to cause the WebView2 to "update" itself when the app's window moves, which will cause any open dropdowns to close themselves (which is normal behavior for dropdowns in web browsers). This avoids the "floating dropdown" issue (because there's nothing to float).

In a Windows App SDK app you should be able to do something like this:

  1. In MainPage.xaml.cs change the constructor to hook up the AppWindow.Changed event:
        public MainWindow()
        {
            this.InitializeComponent();
    
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
            var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
            var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
            if (appWindow != null)
            {
                appWindow.Changed += AppWindow_Changed;
            }
        }
  2. Add a Changed event handler to force the WebView2 to update itself, which will cause the dropdown to close:
        private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
        {
            if (args.DidPositionChange)
            {
                // Whenever the app's window moves, force the WebView2 to update, which will cause any open HTML select's to close (which is normal behavior), and thus not "float around"
                var origMargin = myWebView.Margin;
                myWebView.Margin = new Thickness(myWebView.Margin.Left + 1);
                myWebView.UpdateLayout(); // force the WebView to update its layout, and then immediately set it back
                myWebView.Margin = origMargin;
            }
        }

In a .NET MAUI app this similar should work:

  1. In MainPage.xaml give your BlazorWebView a name (if it doesn't already have one):
    <BlazorWebView HostPage="wwwroot/index.html" x:Name="bwv">
  2. In MainPage.xaml.cs add some code for the Windows platform to detect when the app's window is available, and hook up some events to force the WebView2 (used by BlazorWebView) to update itself, which causes any open dropdown list to close:
        public MainPage()
        {
            InitializeComponent();
        }
    
    #if WINDOWS
        bool _foundWindow;
    
        protected override void OnHandlerChanged()
        {
            base.OnHandlerChanged();
    
            if (!_foundWindow)
            {
                var window = GetParentWindow();
    
                if ((window?.Handler?.PlatformView as MauiWinUIWindow)?.GetAppWindow() is var appWindow)
                {
                    appWindow.Changed += AppWindow_Changed;
                    _foundWindow = true;
                }
            }
        }
    
        private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
        {
            if (args.DidPositionChange)
            {
                // Whenever the app's window moves, force the WebView2 to update, which will cause any open HTML select's to close (which is normal behavior), and thus not "float around"
                var platformWebView = bwv.Handler?.PlatformView as Microsoft.UI.Xaml.Controls.WebView2;
                platformWebView.Width = platformWebView.Width;
            }
        }
    #endif

Please let us know if this helps you in the meantime, until a real fix can be provided. Thanks!

@DrNoLife
Copy link

DrNoLife commented Sep 22, 2022

Just tried the proposed workaround for the .NET MAUI app, Eilon. But it didn't work.

Gave the webview a name, and copy pasted the rest of the code over into MainPage.xaml.cs, however it changed nothing. The bug still persists, at least for MAUI apps.

Gif of the bug still persisting

Edit.

Using the code from the Windows App SDK version (for the .cs file) seems to work. It's a bit funky however, as each movement causes the application to blink which is accompanied with a loading indicator.

Gif of the behaviour described above

@Brosinski

This comment was marked as outdated.

@ispysoftware
Copy link
Author

Seems to work ok in WinUI3

@Brosinski
Copy link

Brosinski commented Sep 26, 2022

@DrNoLife So I found a workaround that works 100% of the time for me with .NET MAUI Blazor

It is the same as @Eilon with the exception that it is targetting the actual window needed to trigger a change in the selects position

MainPage.xaml.cs

public MainPage()
	{
		InitializeComponent();
	}
	#if WINDOWS
    bool _foundWindow;

    protected override void OnHandlerChanged()
    {
        base.OnHandlerChanged();

        if (!_foundWindow)
        {
            var window = GetParentWindow();

            if ((window?.Handler?.PlatformView as MauiWinUIWindow)?.GetAppWindow() is var appWindow)
            {
                appWindow.Changed += AppWindow_Changed;
                _foundWindow = true;
            }
        }
    }

    private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
    {

      
        if (args.DidPositionChange)
        {
            // Whenever the app's window moves, force the WebView2 to update, which will cause any open HTML select's to close (which is normal behavior), and thus not "float around"
            var platformWebView = bwv.Handler?.PlatformView as Microsoft.UI.Xaml.Controls.WebView2;
     
            
                this.WidthRequest = this.Width + 1;
				this.HeightRequest= this.Height + 1;
				this.WidthRequest = sender.Size.Width;
				this.HeightRequest = sender.Size.Height;
				
			
           
            
            }
        else if (args.DidSizeChange)
        {
			this.WidthRequest = sender.Size.Width;
			this.HeightRequest = sender.Size.Height;
		}
       
    }
    
#endif

The change is not registered if you don't make an actual change to WidthRequest or HeightRequest, hence the increment.

Thank you @Eilon, saved my sanity

@TomOeser
Copy link

TomOeser commented Nov 1, 2022

Thanks for the workaround. However, I have now ended up with a self-developed dropdown web component, as the design and functional possibilities of the HTML select element are very limited.
:)

@Eilon
Copy link

Eilon commented Nov 1, 2022

Thanks for the workaround. However, I have now ended up with a self-developed dropdown web component, as the design and functional possibilities of the HTML select element are very limited. :)

Indeed, there are many scenarios that are not supported by an HTML <select>, and using an HTML-based solution would allow you to create a more suitable custom UI.

@acrankyturtle
Copy link

I have this problem using .NET 7 MAUI Blazor and the above workarounds did not resolve my issue. This, however, works for me. This is MainPage.xaml.cs.

using Microsoft.Maui.Platform;

namespace Controller.Application;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
	}

#if WINDOWS
	bool _foundWindow;

	protected override void OnHandlerChanged()
	{
		base.OnHandlerChanged();

		if (!_foundWindow)
		{
			var window = GetParentWindow();

			if ((window?.Handler?.PlatformView as MauiWinUIWindow)?.GetAppWindow() is var appWindow)
			{
				appWindow.Changed += AppWindow_Changed;
				_foundWindow = true;
			}
		}
	}

	private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
	{
		if (args.DidPositionChange)
		{
			var width = this.Window.Width;

			this.Window.Width = width + 1;
			this.Window.Width = width;
		}

	}
#endif
}

@Brosinski
Copy link

Brosinski commented Nov 30, 2022

I have this problem using .NET 7 MAUI Blazor and the above workarounds did not resolve my issue. This, however, works for me. This is MainPage.xaml.cs.

That would only update the select position when moving the screen, resizing the screen would still cause the error. Please refer to my solution above or below
MainPage.xaml.cs

using Microsoft.Maui.Platform;

namespace Controller.Application;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
	}

#if WINDOWS
	bool _foundWindow;

	protected override void OnHandlerChanged()
	{
		base.OnHandlerChanged();

		if (!_foundWindow)
		{
			var window = GetParentWindow();

			if ((window?.Handler?.PlatformView as MauiWinUIWindow)?.GetAppWindow() is var appWindow)
			{
				appWindow.Changed += AppWindow_Changed;
				_foundWindow = true;
			}
		}
	}

	private void AppWindow_Changed(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowChangedEventArgs args)
	{
		if (args.DidPositionChange)
		{
			var width = this.Window.Width;

			this.Window.Width = width + 1;
			this.Window.Width = width;
		} 
           else if (args.DidSizeChange)
                {
			this.WidthRequest = sender.Size.Width;
			this.HeightRequest = sender.Size.Height;
		}

	}
#endif
}

@Mathyn
Copy link

Mathyn commented Dec 7, 2022

Is the work around shared in this issue still working properly? When I use it I find that if I already have the dropdown opened and I move the window the dropdown does not move with the window.

After closing and reopening the dropdown it does show up in the right location.

One of the comments in the work around says

// Whenever the app's window moves, force the WebView2 to update, which will cause any open HTML select's to close (which is normal behavior), and thus not "float around"

However this does not appear to be true (at least on my system), the dropdowns remain open. This is for a Windows 10 system.

@acrankyturtle
Copy link

Is the work around shared in this issue still working properly? When I use it I find that if I already have the dropdown opened and I move the window the dropdown does not move with the window.

After closing and reopening the dropdown it does show up in the right location.

One of the comments in the work around says

// Whenever the app's window moves, force the WebView2 to update, which will cause any open HTML select's to close (which is normal behavior), and thus not "float around"

However this does not appear to be true (at least on my system), the dropdowns remain open. This is for a Windows 10 system.

That workaround did not work for me either. I am also on Windows 10. I posted a workaround above that did work for me.

@ispysoftware
Copy link
Author

I'm finding it hard to believe that this issue is still open and not resolved yet. It's a major bug and it's been there for almost a year. It's not very reassuring to develop on these platforms when bugs like this are just left unresolved for extended periods of time.

@champnic - could we please get a proper resolution to this major issue?

@champnic
Copy link
Member

champnic commented Jan 6, 2023

This is high on our list and we hope to investigate and get a fix out soon. Is this a common scenario for folks, to open a select and then resize or move a window without dismissing or interacting with the select dropdown? ie. did you find this in manual testing, or are you hearing it from lots of end users?

@ispysoftware
Copy link
Author

ispysoftware commented Jan 7, 2023

You don't need to not dismiss it, you just need to have opened it once, then you can dismiss it, move the window, open it again and the drop-down overlay is locked in it's original position.

I've got no feedback about user experience as this issue has prevented us from ever deploying the WinUI version of our application - it makes it look like a broken mess. Also we're stuck on "preview" nuget packages which is preventing us from even uploading the application to the store.

We also have an ongoing issue with WinUI somehow interfering with our native threading code (some incompatibility with pthread and windows threads we suspect) which intermittently hangs the webrtc code side of our application.

@Mathyn
Copy link

Mathyn commented Jan 8, 2023

@champnic We are hearing about this issue from our end users. On top of that like @ispysoftware mentioned this makes the application look messy and unprofessional.

On our side we have decided to switch to a HTML replacement for the dropdown which solved the issue for us. None of the work arounds found online really worked in all cases for us (those which fixed it causes other issues).

@TomOeser
Copy link

TomOeser commented Jan 8, 2023

@champnic
Simply put, what do users who are used to the correct behaviour of a select from everyday browsing expect? Correct - it should appear in the right position. It should be displayed correctly. It should be moved with the window and then again displayed or opened at the correct position. It must comprehensively cover the expected functionality. Such elementary errors leave the end customer with the stale aftertaste: "My goodness, these software developers can't get it right, but they also demand money from us in return." The rest of the software can be as good as it wants to be, customers quickly get upset by something like this - and that's all that gets noticed from then on. "Your software works, we save time and money, but your dropdowns - no way!

As a developer, you assume that a dropdown behaves as you expect it to.

Please address this problem. I'm using my own solution now, but I'm thinking of the novice developers who are just starting out.

@dady8889
Copy link

dady8889 commented Jan 8, 2023

I had a similar problem with WebView in MAUI Hybrid Blazor app, when opening and using a color picker.
Thankfully, I stumbled upon this thread and was able to combine my solution with the code available here.

The code already presented to fix this issue has awful performance, as the redraw happens on every move message. I was able to optimize it as follows:

            builder.ConfigureLifecycleEvents(events =>
            {
#if WINDOWS
                events.AddWindows(windows => windows
                       .OnPlatformMessage((window, args) =>
                       {
                           // force redraw of webview => causes all popups to close
                           if (args.MessageId == 561) // WM_ENTERSIZEMOVE
                           {
                               var mauiWindow = window.GetWindow();
                               if (mauiWindow != null)
                               {
                                   var blazorWebView = (mauiWindow.Content as MainPage)?.Content as BlazorWebView;
                                   if (blazorWebView != null)
                                   {
                                       var platformWebView = blazorWebView.Handler?.PlatformView as WebView2;
                                       if (platformWebView != null)
                                       {
                                           var margin = platformWebView.Margin;
                                           platformWebView.Margin = new Microsoft.UI.Xaml.Thickness(platformWebView.Margin.Left + 1);
                                           platformWebView.UpdateLayout();
                                           platformWebView.Margin = margin;
                                       }
                                   }
                               }

                               // System.Diagnostics.Debug.WriteLine($"WM_ENTERSIZEMOVE");
                           }

                           // force resize => causes popups to show at the correct location
                           else if (args.MessageId == 562) // WM_EXITSIZEMOVE
                           {
                               var windowsWindow = window.GetAppWindow();
                               if (windowsWindow != null)
                               {
                                   var size = windowsWindow.Size;
                                   windowsWindow.Resize(new Windows.Graphics.SizeInt32(size.Width + 1, size.Height));
                                   windowsWindow.Resize(new Windows.Graphics.SizeInt32(size.Width, size.Height));
                               }
                               
                               // System.Diagnostics.Debug.WriteLine($"WM_EXITSIZEMOVE");
                           }
                       })
                );
#endif
});

Add this code into your CreateMauiApp builder in the MauiProgram class to use it.
You can uncomment the Debug.WriteLine, and see that it will be called only at move start/end.
This code works correctly for the color picker on MAUI, I believe it will also work for any other popups.

I would just add, that the issue is not that users open and then move the window (even though it still should close the popup or move the popup along with the window). The popup will never move from the initial position unless the window is resized, even after opening/closing of the popup, which is a major bug (but this may be for the MAUI team and not WebView...).

@champnic
Copy link
Member

champnic commented Jan 9, 2023

Thanks for the info all! I was under the impression this only happened when the dropdown was kept open. For example, @Mathyn reports:

After closing and reopening the dropdown it does show up in the right location.

Whereas it sounds like this also happens with incorrect positioning even when the dropdown has been dismissed and reopened. For those seeing this behavior, just want to confirm whether you are seeing this on WinUI 2 or WinUI 3 (WindowsAppSDK) or other?

@mikeduglas
Copy link

@champnic I see this behavior on WinForms (SDK 1.0.1466.0) and 111.0.1605.0 canary runtime.

@danroth27
Copy link

just want to confirm whether you are seeing this on WinUI 2 or WinUI 3 (WindowsAppSDK) or other?

@champnic The .NET MAUI uses WinUI 3 under the covers.

@TomOeser
Copy link

TomOeser commented Jan 9, 2023

@champnic I see this behavior on WPF (SDK current version, current canary)

@Mathyn
Copy link

Mathyn commented Jan 24, 2023

@champnic I see this behavior using .NET Maui (so WinUI3).

@johna-ms
Copy link
Contributor

johna-ms commented Mar 2, 2023

Hi all. I'm the dev that's most recently looked at this issue. The problem of the select dropdown reopening in a stale location looks to be an issue with the control not calling the NotifyParentWindowPositionUpdated API. This is unfortunately not a publicly exposed API for Maui. I believe this would be an issue on WinUI3 so please file one with them.

The problem of the select dropdown not dismissing on click+drag remains legit and on us.

@johna-ms
Copy link
Contributor

johna-ms commented Mar 16, 2023

I didn't notice that a workaround was already provided by WinApp folks above about a year ago. I'm seeing that the remaining commenters are finding the workaround insufficient. Could commenters get specific about issues with the workaround are so we can work with WinUI to see if they can be addressed?

@ispysoftware @Mathyn

@ispysoftware
Copy link
Author

Work around seems OK here. Seems some people above are having performance issues with it - I guess if hacking at the browser margin to force a complete redraw and thereby collapse a select dropdown on movement is good enough for Microsoft then it's good enough for us. Doesn't sit well with my OCD.

@cbra-caa
Copy link

We are also experiencing it in WPF. For those running with the workaround, has anyone felt an impact on performance from rerendering when dragging / min-maxing?

@Optimierungswerfer
Copy link

This issue does not seem to be platform-specific, because we are using CoreWebView2 directly through C++/WinRT (previously Win32) without any framework wrappers (WPF/WinUI/etc.) in our MFC application and still run into the dropdown-position not updating when moving the window while the dropdown is open.

SDK Version: 1.0.1901.177 (latest)
Runtime Version: 115.0.1901.203 (latest stable evergreen)

@johna-ms
Copy link
Contributor

@Optimierungswerfer this can happen if you are not calling NotifyParentWindowPositionChanged when the parent window position changes. Are you calling this API?

@Optimierungswerfer
Copy link

Yes, we are calling NotifyParentWindowPositionChanged whenever the parent window moves. We do that to explicitly fix the issue with stuck/floating elements like the search bar (Ctrl+F) or the download pop-up. However, open HTML drop-down menus being stuck are surprisingly not fixed by this.

Actually, the place where we call NotifyParentWindowPositionChanged was exactly where I also tried the resize-workaround that is suggested here. That causes noticeable jittering when moving the window though, which we do not want, so the workaround is no option for us.

@Martin12350
Copy link

@dady8889 Thanks for this. Only solution that works properly and to the top of it solves the lagging/performance issue.
Solutions above unfortunately never closed the dropdown, and changing WidthRequest/HeightRequest also somehow messed up the styling.

For those who do not like nested ifs, here is a compacted version:

if (args.MessageId == WM_ENTERSIZEMOVE)
   if (window.GetWindow()?.Content is MainPage { Content: BlazorWebView { Handler.PlatformView: WebView2 platformWebView  } })
   ...

@ispysoftware
Copy link
Author

ispysoftware commented Oct 7, 2023

@champnic Is this ever going to be fixed?
The workarounds work but have some serious side effects - we're playing video and now when the window is moved the video flickers badly because of the forced redraw. We're having to tell our users that it's because Microsoft don't fully support Select elements in their web browser control which is embarrassing all round (and also they find hard to believe).

@CorbynBMG
Copy link

Almost half way through 2024 and this issue still persists.

@johna-ms
Copy link
Contributor

johna-ms commented Apr 27, 2024

@ispysoftware @CorbynBMG it's been mentioned earlier, but the fix for the issue of select dropdown positioning that would resolve the performance issues is actually work on the WinUI team microsoft-ui-xaml. I don't see an open github issue on their side tracking it. This one was opened recently though and that appears to be the same issue. Please let them know and tag this issue so they can take your feedback into consideration regarding priority.

@Optimierungswerfer I've tried to repro the select dropdown positioning in a local C++/WinRT app but I cannot. Please let me know what you are doing or link a min-repro sample app so I can help diagnose what's going on

@ispysoftware
Copy link
Author

ispysoftware commented Apr 27, 2024

@johna-ms This issue has been open for over 2 years - it's a generic select element not working properly in your web browser control. If that's not a critical bug i'm not sure what is. This isn't some rare edge case thing.

Someone at microsoft needs to take ownership of it and get it fixed instead of telling people to log cases elsewhere.

@jefflord
Copy link

@johna-ms @ispysoftware @CorbynBMG

I agree that it's insane that this is not consider a showstopper type bug. I am using Photino and was baffled when I ran into this.

I just gave up and moved on. I switched to select2. It is an upgrade and works without any issues at all. select2 is not perfect and there are other options (Tom Select, Selectize.js, Chosen (deprecated), Choices.js), but I have history with select2.

I am just following this issue because of the trainwreck it is. I agree with ispysoftware, the finger pointing and buck passing it crazy.

But this is the world we live in now. If you build something using a component, and that component has a bug, no matter how big and bad it is for you, it might not even be a use case that's considered by owner.

@Optimierungswerfer
Copy link

Any Updates?

@johna-ms You can repro this in your WebView2Samples app by visiting any page with a HTML select element (e.g. https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select), opening the dropdown and then moving the window.

@VassilisM
Copy link

I'll pester too, as it is still an issue.

@ispysoftware
Copy link
Author

OMFG i can't believe this is still going on! hahaha

@VassilisM
Copy link

Well having the select dropdowns flying around "somewhere" on the screen, is not something to easily let go of.
Oh, the same goes for the element tooltips when the "title" attribute is defined. Has anyone tried it yet? Yes, another funny story; you hover your mouse on top of, say, buttons and the tooltip description is sometimes there and sometimes at the edges of the known universe...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working tracked We are tracking this work internally.
Projects
None yet
Development

No branches or pull requests