-
Notifications
You must be signed in to change notification settings - Fork 635
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
Dyn 5107 webview2 update in guided tours #13142
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Windows; | ||
using System.Windows.Controls; | ||
using System.Windows.Controls.Primitives; | ||
using System.Windows.Input; | ||
using Dynamo.Utilities; | ||
using Dynamo.Wpf.UI.GuidedTour; | ||
using Dynamo.Wpf.ViewModels.GuidedTour; | ||
using Microsoft.Web.WebView2.Wpf; | ||
|
||
namespace Dynamo.Wpf.Views.GuidedTour | ||
{ | ||
|
@@ -23,7 +28,11 @@ public partial class PopupWindow : Popup | |
//Field that indicates wheter popups are left-aligned or right-aligned | ||
private const string menuDropAligment = "_menuDropAlignment"; | ||
|
||
internal WebBrowserWindow webBrowserWindow; | ||
internal WebView2 webBrowserComponent; | ||
//Assembly path to the Font file | ||
private const string mainFontStylePath = "Dynamo.Wpf.Views.GuidedTour.HtmlPages.Resources.ArtifaktElement-Regular.woff"; | ||
//Assembly path to the Resources folder | ||
private const string resourcesPath = "Dynamo.Wpf.Views.GuidedTour.HtmlPages.Resources"; | ||
|
||
public PopupWindow(PopupWindowViewModel viewModel, HostControlInfo hInfo) | ||
{ | ||
|
@@ -75,10 +84,13 @@ private void EnsureStandardPopupAlignment() | |
|
||
private void PopupWindow_Closed(object sender, EventArgs e) | ||
{ | ||
if (webBrowserWindow != null) | ||
webBrowserWindow.IsOpen = false; | ||
if (webBrowserComponent != null) | ||
{ | ||
webBrowserComponent.Visibility = Visibility.Collapsed; | ||
} | ||
|
||
|
||
if(isClosingTour) | ||
if (isClosingTour) | ||
{ | ||
Opened -= PopupWindow_Opened; | ||
Closed -= PopupWindow_Closed; | ||
|
@@ -89,11 +101,77 @@ private void PopupWindow_Opened(object sender, EventArgs e) | |
{ | ||
if (hostControlInfo.HtmlPage != null && !string.IsNullOrEmpty(hostControlInfo.HtmlPage.FileName)) | ||
{ | ||
ContentRichTextBox.Visibility = Visibility.Hidden; | ||
ContentRichTextBox.Visibility = Visibility.Hidden; | ||
InitWebView2Component(); | ||
} | ||
} | ||
|
||
webBrowserWindow = new WebBrowserWindow(popupViewModel, hostControlInfo); | ||
webBrowserWindow.IsOpen = true; | ||
private async void InitWebView2Component() | ||
{ | ||
webBrowserComponent = new WebView2(); | ||
webBrowserComponent.Margin = new System.Windows.Thickness(popupBordersOffSet, 0, 0, 0); | ||
webBrowserComponent.Width = popupViewModel.Width; | ||
//The height is subtracted by a const that sums the height of the header and footer of the popup | ||
var heightBottom = bottomGrid.ActualHeight; | ||
var heightTitle = titleGrid.ActualHeight; | ||
//popupBordersOffSet * 2 because is one offset at the top and the other one at the bottom of the Popup | ||
webBrowserComponent.Height = popupViewModel.Height - (heightBottom + heightTitle + popupBordersOffSet * 2); | ||
contentGrid.Children.Add(webBrowserComponent); | ||
Grid.SetRow(webBrowserComponent, 1); | ||
|
||
LoadWebBrowser(hostControlInfo.HtmlPage); | ||
QilongTang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// <summary> | ||
/// Loads HTML file from resource assembly and replace it's key values by base64 files | ||
/// </summary> | ||
/// <param name="htmlPage">Contains filename and resources to be loaded in page</param> | ||
private async void LoadWebBrowser(HtmlPage htmlPage) | ||
{ | ||
var bodyHtmlPage = ResourceUtilities.LoadContentFromResources(htmlPage.FileName, GetType().Assembly, false, false); | ||
|
||
bodyHtmlPage = LoadResouces(bodyHtmlPage, htmlPage.Resources); | ||
bodyHtmlPage = LoadResourceAndReplaceByKey(bodyHtmlPage, "#fontStyle", mainFontStylePath); | ||
await webBrowserComponent.EnsureCoreWebView2Async(); | ||
webBrowserComponent.NavigateToString(bodyHtmlPage); | ||
QilongTang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// <summary> | ||
/// Loads resource from a dictionary and replaces its key by an embedded file | ||
/// </summary> | ||
/// <param name="bodyHtmlPage">Html page string</param> | ||
/// <param name="resources">Resources to be loaded</param> | ||
/// <returns></returns> | ||
private string LoadResouces(string bodyHtmlPage, Dictionary<string, string> resources) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a good thing is to add those methods in the Utils class, so they can be reused. (For example in our notifications extension method). Let me know your opinion about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The methods LoadWebBrowser, LoadResouces and LoadResourceAndReplaceByKey were moved to the ResourceUtilities class so they can be used in other places, please check the next commit: |
||
{ | ||
if (resources != null && resources.Any()) | ||
{ | ||
foreach (var resource in resources) | ||
{ | ||
bodyHtmlPage = LoadResourceAndReplaceByKey(bodyHtmlPage, resource.Key, $"{resourcesPath}.{resource.Value}"); | ||
} | ||
} | ||
return bodyHtmlPage; | ||
} | ||
|
||
/// <summary> | ||
/// Finds a key word inside the html page and replace by a resource file | ||
/// </summary> | ||
/// <param name="bodyHtmlPage">Current html page</param> | ||
/// <param name="key">Key that is going to be replaced</param> | ||
/// <param name="resourceFile">Resource file to be included in the page</param> | ||
/// <returns></returns> | ||
private string LoadResourceAndReplaceByKey(string bodyHtmlPage, string key, string resourceFile) | ||
{ | ||
Stream resourceStream = ResourceUtilities.LoadResourceByUrl(resourceFile); | ||
|
||
if (resourceStream != null) | ||
{ | ||
var resourceBase64 = ResourceUtilities.ConvertToBase64(resourceStream); | ||
bodyHtmlPage = bodyHtmlPage.Replace(key, resourceBase64); | ||
} | ||
|
||
return bodyHtmlPage; | ||
} | ||
|
||
private void StartTourButton_Click(object sender, System.Windows.RoutedEventArgs e) | ||
|
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RobertGlobant20 Can you explain when is the
webBrowserComponent
disposed?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@QilongTang the WebView2 control is created every time the Popup is opened and disposed when the Popup is Hidden (specifically in the Step.Hide() method that is executed when we click the next or prev Popup button), the problem with Popup.IsOpen = false is that it generates an async call to Popup.OnClose() so if we don't dispose the WebView2 instance before we close the PackageManagerSearch, the WebView2 crashes (in the image below you will see that we set IsOpen = false and then we execute the UIAutomation Steps - inside one of this we are closing PackageManagerSearch).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RobertGlobant20 Gotcha, thanks!