Microsoft.Toolkit.Win32 icon indicating copy to clipboard operation
Microsoft.Toolkit.Win32 copied to clipboard

How to read/write values in loaded form?

Open znakeeye opened this issue 4 years ago • 5 comments

Consider the oldschool WebBrowser component. To read/write to an element, you would simply do this:

var htmlDom = (HTMLDocument)webBrowser.Document;
var element = htmlDom.getElementById("id");
element.setAttribute("value", "foo");

Now, using WebBrowserCompatible these APIs are not available. So how can you accomplish the above?

I read somewhere that you should use Javascript. So how do you do that when there is no way to evaluate javascript code? I tried this, but it scriptName is, well, not a script name, so it fails:

string result = webViewCompatible.InvokeScript($"eval(document.getElementById(\"{id}\"))");

You are hiding all relevant APIs in the inner WebView. I guess the only way forward is to use the obsolete WebView in place of WebViewCompatible?

znakeeye avatar May 22 '20 12:05 znakeeye

Hello znakeeye, thank you for your interest in Win32!

I have automatically added a "needs triage" label to help get things started. Our team will look into the question and answer ASAP. Other community members may also answer the question and provide feedback 🙌

ghost avatar May 22 '20 12:05 ghost

Since you don't expose InvokeScript() with arguments, I don't think this can be solved without advanced hacks.

Please add these APIs:

public string InvokeScript(string scriptName, params string[] arguments)
public string InvokeScript(string scriptName, IEnumerable<string> arguments)

Otherwise we will have to use the deprecated WebView or use reflection to get hold of it.

public class UsableWebBrowser : WebViewCompatible
{
    private readonly WebBrowser browser;
    private readonly WebView webView;

    public UsableWebBrowser()
    {
        var fieldInfo = typeof(WebViewCompatible).GetField("_implementation", BindingFlags.NonPublic | BindingFlags.Instance);
        var adapter = (IWebViewCompatibleAdapter)fieldInfo.GetValue(this);
        
        var browserFieldInfo = adapter.GetType().GetField("_browser", BindingFlags.NonPublic | BindingFlags.Instance);
        if (browserFieldInfo != null)
        {
            browser = (WebBrowser)browserFieldInfo.GetValue(adapter);
        }
        else
        {
            var webViewFieldInfo = adapter.GetType().GetField("_webView", BindingFlags.NonPublic | BindingFlags.Instance);
            webView = (WebView)webViewFieldInfo.GetValue(adapter);
        }
    }
}

At least we have the WebViewCompatible.IsLegacy property to determine if the WebView is expected to work, but putting a WebView in XAML requires disabling some worrying warnings.

znakeeye avatar May 22 '20 13:05 znakeeye

This issue has been marked as "needs attention 👋" due to no activity for 15 days. Please triage the issue so the fix can be established.

ghost avatar Jun 06 '20 14:06 ghost

This issue has been marked as "needs attention 👋" due to no activity for 15 days. Please triage the issue so the fix can be established.

ghost avatar Jun 21 '20 14:06 ghost

@znakeeye WebViewCompatible is also deprecated, it's just a wrapper around the WebView control. You should move over to WebView2.

FYI @pagoe-msft

michael-hawker avatar Jun 22 '20 23:06 michael-hawker