|
| 1 | + |
| 2 | +WPF Airspace - WebView2CompositionControl |
| 3 | +=== |
| 4 | + |
| 5 | +# Background |
| 6 | +For a long time, the WebView2 WPF control has had airspace issues, where the WebView2 control will always |
| 7 | +be the top-most control in the WPF app. Any WPF element in the same location as the WebView2 control will |
| 8 | +end up below the WebView2 control and be "invisible" to the end-user. This issue stems from the fact that |
| 9 | +our WPF control uses the WPF HwndHost to host the Win32 WebView2 control, and HwndHost has a long-standing |
| 10 | +issue with airspace. This issue has existed for over a decade, and you can read more about in-depth efforts to fix |
| 11 | +it in general in WPF here: |
| 12 | +https://dwayneneed.github.io/wpf/2013/02/26/mitigating-airspace-issues-in-wpf-applications.html |
| 13 | + |
| 14 | +Solving this issue for WebView2 necessitates moving away from the HwndHost and the windowed hosting model |
| 15 | +of WebView2, and instead use visuals to host the WebView2. To avoid compatibility issues and introducing |
| 16 | +new regressions in the existing control, we decided to create a new WebView2 WPF control, called the WebView2CompositionControl. |
| 17 | + |
| 18 | +# Examples |
| 19 | +In this example we create a WebView2CompositionControl in exactly the same way we would a regular |
| 20 | +WebView2 control in WPF. Additionally, we place a pink Label that appears ABOVE the WebView2CompositionControl. |
| 21 | +If you were to instead do this with the regular WebView2 control, the Label would be hidden behind it. |
| 22 | +```xml |
| 23 | + <DockPanel> |
| 24 | + |
| 25 | + <DockPanel |
| 26 | + DockPanel.Dock="Top"> |
| 27 | + <Button |
| 28 | + x:Name="ButtonGo" |
| 29 | + DockPanel.Dock="Right" |
| 30 | + Click="ButtonGo_Click" |
| 31 | + Content="Go" /> |
| 32 | + <TextBox Name="addressBar"/> |
| 33 | + </DockPanel> |
| 34 | + <Grid> |
| 35 | + <wv2:WebView2CompositionControl |
| 36 | + Name="webView" |
| 37 | + Source="https://www.microsoft.com" |
| 38 | + AllowExternalDrop="False"/> |
| 39 | + <Label |
| 40 | + Content="This is a label over the WebView2!" |
| 41 | + Background="LightPink" |
| 42 | + Height="100" |
| 43 | + Width="300"/> |
| 44 | + </Grid> |
| 45 | + </DockPanel> |
| 46 | +``` |
| 47 | + |
| 48 | + |
| 49 | +# API Details |
| 50 | +If you are building a Windows Presentation Foundation (WPF) app and using the WebView2 control, you |
| 51 | +may find that your app runs into "airspace" issues, where the WebView2 control will always show up |
| 52 | +on top and hide any WPF elements in the same location, even if you try to specify the WPF elements |
| 53 | +to be above the WebView2 control (using visual tree order or the z-index property, for example). To |
| 54 | +solve this issue you should use the WebView2CompositionControl. |
| 55 | + |
| 56 | +The WebView2CompositionControl is a drop-in replacement |
| 57 | +for the standard WPF WebView2 control - both the WebView2 control and the WebView2CompositionControl |
| 58 | +implement the [Microsoft.Web.WebView2.Wpf.IWebView2](https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.wpf.iwebview2?view=webview2-dotnet-1.0.2739.15) |
| 59 | +interface, as well as derive from FrameworkElement (`FrameworkElement -> HwndHost -> WebView2`, and |
| 60 | +`FrameworkElement -> Control -> WebView2CompositionControl`). So anywhere you use |
| 61 | +WebView2, you can instead change to a WebView2CompositionControl without changing your |
| 62 | +code. |
| 63 | + |
| 64 | +We chose the name "WebView2CompositionControl" because it matches our naming convention |
| 65 | +for visual hosting WebView2, which uses the CoreWebView2CompositionController instead |
| 66 | +of the CoreWebView2Controller. |
| 67 | + |
| 68 | +# Appendix |
| 69 | +At a high level, the WebView2CompositionControl instantiates a CoreWebView2 in much the same way as |
| 70 | +the regular WebView2 control, but connects to it and controls it using the CoreWebView2CompositionController |
| 71 | +instead of the CoreWebView2Controller. The composition controller is given a WinComp visual to draw into, |
| 72 | +and this visual is used to create a GraphicsCaptureSession. When frames from this capture session are |
| 73 | +captured they are they rendered into a WPF Image element that's part of the control. |
0 commit comments