Invoking webview's DomContentLoaded event in the view model

Tyler Lucas 21 Reputation points
2020-02-25T01:55:28.587+00:00

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://learn.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.

Universal Windows Platform (UWP)
{count} votes

Accepted answer
  1. Richard Zhang-MSFT 6,936 Reputation points
    2020-02-26T05:55:04.033+00:00

    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

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.