0
votes

I am attempting to get the currently selected text from an arbitrary website shown in a UWP WebView to the UWP App written in C#. I have tried several methods, but the Async calls:-

return await myWebView.InvokeScriptAsync("eval", new string[] { "return document.getSelection.toString();" });

,

await myWebView.InvokeScriptAsync("eval", new string[] { "document.body.innerHTML = document.getSelection.toString();" });

and

DataPackage data = await web.CaptureSelectedContentToDataPackageAsync();
return await data.GetView().GetTextAsync();

keep hanging and causing an infinite loop.

I have gotten simple DOM Model editing code to be injected via the InvokeScriptAsync, but as soon as I try document.getSelection() or window.getSelection(), the whole program just freezes forever.

I saw this post Windows UWP - WebView get selected Text but that does seem to be working for me, even though I am working on a PC.

2

2 Answers

0
votes

As it turns out, the problem was that InvokeScriptAsync() appears to expect to be in a function that has a parameter that is an object with a Uri object as a property. Before I was doing this (which was not working):

private async Task<string> GrabSelectedText(WebView web)
    {
        try
        {
            return await web.InvokeScriptAsync("eval", new string[] { @"window.getSelection().toString();" });

        }catch(Exception e)
        {
            return "Exception from GrabSelectedText: " + e.Message;
        }

    }

However, by adding an additional parameter of an object with a Uri object as a property (like in the WebViewDOMContentLoadedEventArgs found here: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.webviewdomcontentloadedeventargs?cs-save-lang=1&cs-lang=csharp#code-snippet-1).

The following code is what I found to work:

public class MockArgs
{
    private Uri uri;

    private MockArgs(Uri uri)
    {
        this.uri = uri;
    }

    public static MockArgs Create(Uri arg)
    {
        return new MockArgs(arg);
    }
}

/** This is in a separate class that is able to see the above protected class*/
public async void GetSelectedText(WebView sender, MockArgs mockArgs)
    {
        var s = await sender.InvokeScriptAsync("eval", new string[] { @"window.getSelection().toString(); " });
        Debug.WriteLine("selection retreived");
    }

/** This is called from anywhere that needs to get the selected text from a WebView (that can see the above GetSelectedText() method. */
public void TestCode(WebView sender){
        GetSelectedText(sender, MockArgs.Create(args.Uri));
     }
0
votes

but as soon as I try document.getSelection() or window.getSelection(), the whole program just freezes forever.

Your js code was not correct, I used the following code to test. It worked well.

<WebView x:Name="wv" Source="https://msdn.microsoft.com/en-us/default.aspx"/>
<Button Content="get selected text" Click="Button_Click"></Button>
private async void Button_Click(object sender, RoutedEventArgs e)
{
    try
    {
        string[] arguments = new string[] { @"window.getSelection().toString();" };
        var s = await wv.InvokeScriptAsync("eval", arguments);
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
}