question

TylerLucas-6809 avatar image
0 Votes"
TylerLucas-6809 asked ·

Invoking webview's DomContentLoaded event in the view model

I'm having problems implementing the webView's DOMContentLoaded event within my view model. I want to execute the code on the web page after the DOMContentLoaded event. I read the documentation about the event here, https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.webview.domcontentloaded, however I'm having problems implementing it. Below is the code I currently have:

 WebView webView = new WebView();
 webView.Navigate(new Uri(url));
 webView.DOMContentLoaded += DOMContentLoaded;
 // event handling for dom content loaded
         public event TypedEventHandler<WebView, WebViewDOMContentLoadedEventArgs> DOMContentLoaded
         {
 
         }^ This is from the documentation

Currently, it's giving me an error that says, "event property must have both add and remove accessors.". I understand how to use events in the XAML because it's super easy and does most of the work for me, but since I'm using the webview in the view model (to scrape and get some information on a web page), I need to wait for the page to load and then do the scraping. How can I do that in the view model?

EDIT:

Great Question. So in the ViewModel I'm using the WebView as a scraper. Here are the functions that will use it and some more details.

 public async void UPCSearch(object sender, KeyRoutedEventArgs e)
         {
             if (e.Key == Windows.System.VirtualKey.Enter)
             {
                 /*
                 // search Walmart
                 try {
                     await searchWalmartNF();
                     //if (!found || !walmartInformation)
                 } catch (HttpRequestException httpException) {
                     Debug.WriteLine("HTTP exception caught.");
                     Debug.WriteLine(httpException);
                 } catch (Exception exception) {
                     Debug.WriteLine("Exception caught.");
                     Debug.WriteLine(exception);
                 }*/
 
                 // search Target
                 try {
                     **await searchTargetNF();**
                 } catch (HttpRequestException httpException) {
                     Debug.WriteLine("HTTP exception caught.");
                     Debug.WriteLine(httpException);
                 } catch (Exception exception) {
                     Debug.WriteLine("Exception caught.");
                     Debug.WriteLine(exception);
                 }
 
                 
                 // search CVS
                 try
                 {
                     **await searchCVSNF();**
                 }
                 catch (HttpRequestException httpException)
                 {
                     Debug.WriteLine("HTTP exception caught.");
                     Debug.WriteLine(httpException);
                 }
                 catch (Exception exception)
                 {
                     Debug.WriteLine("Exception caught.");
                     Debug.WriteLine(exception);
                 }
 
                 // if a price was found
                 if (found)
                 {
                     operationClicked = false;
                     calculated = true;
                     hasDecimal = false;
                     displayText = onlinePrice.ToString();
                     textblockPrice = onlinePrice.ToString() + onlineAbbrev;
                 }
                 else
                 {
                     var messageDialog = new MessageDialog("No price was found online.");
                     await messageDialog.ShowAsync();
                 }
 
                 // reset found
                 found = false;
             }
         }

 public async Task **searchTargetNF()**
         {
             try
             {
                 string targetURL = "https://www.target.com/s?searchTerm=";
                 url = (targetURL + upc);
 
 
                 webView.Navigate(new Uri(url));
                 webView.DOMContentLoaded += DOMContentLoaded;
 
                 //super.onPageFinished(webView, url);
                 
                 // delay to ensure navigation completes
                 **await Task.Delay(6500);**
                 string html = await webView.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
                 var text = html;
                 var doc = new HtmlDocument();
                 doc.LoadHtml(text);
 
                 var price = doc.DocumentNode.SelectSingleNode("//*[@id=\"mainContainer\"]/div[3]/div[2]/div/div[1]/div[3]/div/ul/li/div/div[2]/div/div/div/div[2]/span");
                 //var price = doc.DocumentNode.SelectNodes("//div[@class='styles__StyledPricePromoWrapper-e5kry1-12 gzebgK']");
                 Debug.WriteLine("Target price found:");
                 Debug.WriteLine(price.InnerText);
             }
             catch (HttpRequestException httpException)
             {
                 Debug.WriteLine("HTTP exception caught.");
                 Debug.WriteLine(httpException);
             }
             catch (Exception exception)
             {
                 Debug.WriteLine("Exception caught.");
                 Debug.WriteLine(exception);
             }
         }

Currently, the searchWalmart() function uses Walmart's API, so that doesn't need the WebView. However, searchTargetNF() uses the WebView to scrape, and needs to wait for the page to load to scrape the information on the page. It does get the information it needs with the wait timer, but it isn't practical to wait 6.5s for each web page that it views to get the information. The variables such as UPC are entered in from the UI side and the ViewModel works with that info to return product prices back to the UI.

The goal is to execute the code in searchTargetNF() after the DOMContentLoaded event, and return product prices to the UI side.

uwpuwp-xaml
· 2
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, Only event definitions are given in the documentation, not event handling code. I noticed that you created a WebView in your code, did you add it to the UI Visual Tree (the DOM won't render if you don't add WebView to UI), can you provide more code about this ViewModel?

0 Votes 0 · ·

Sure, I edited the post to include the couple functions that will use it. I don't think I added the UI to the Visual Tree. All it's doing is navigating to the page and then I'm scraping the info from the page so I didn't realize I needed to do that.

0 Votes 0 · ·

1 Answer

RichardZhang-MSFT avatar image
0 Votes"
RichardZhang-MSFT answered ·

Hello,​

Welcome to our Microsoft Q&A platform!

If you try to add DOMContentLoaded event to WebView, you can write like this:

 webView.DOMContentLoaded += DOMContentLoaded;
  public void DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
  {
      // do something...
  }

But in your case, even listening to the DOMContentLoaded event may not be useful.

The webpage you provided is loaded locally before getting detailed data and rendering. This means that when the DOMContentLoaded event is triggered, there are no search results on your page.

It is recommended that you obtain relevant data through the API instead of parsing the web page.

Thanks

· Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.