0

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.

Community
  • 1
  • 1
lorkaan
  • 141
  • 7

2 Answers2

0

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);
    }
}
Xie Steven
  • 8,544
  • 1
  • 9
  • 23
  • I literally just tried the javascript code you put there to test, and all it does is freeze the whole program, giving me this message The thread 0x19cc has exited with code 0 (0x0). – lorkaan Jan 26 '17 at 15:19
  • @lorkaan I've updated my entire code sample, please check it. – Xie Steven Jan 27 '17 at 01:49
  • Thanks, I worked it out and posted the answer on this thread as the accepted answer. It had to do with the specific parameters of the function where the InvokeScriptAsync was being called. – lorkaan Feb 01 '17 at 15:36
0

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));
     }
lorkaan
  • 141
  • 7