Elio
Elio

Reputation: 23

How can I make my webview2 control catch a button click of an HTML button

I basically need to create a windows form with bootstrap components. The windows form includes a login URL, email, API key fields, and a submit button. I'm creating it using webview2 control like this :

        {
            string html = @"<html>
            <head>
            <link rel=""stylesheet"" href=""https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"" integrity=""sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"" crossorigin=""anonymous"">
            <script src=""https://code.jquery.com/jquery-3.3.1.slim.min.js"" integrity=""sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"" crossorigin=""anonymous""></script>
            <script src=""https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"" integrity=""sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"" crossorigin=""anonymous""></script>
            <script src=""https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"" integrity=""sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"" crossorigin=""anonymous""></script>
            </head>
            <body>
            <form>
            <div class=""form-group"">
            <label for=""jiraurl"">Jira Url</label>
            <input type=""url"" class=""form-control"" id=""jiraurl""  placeholder=""Enter Jira URL"">
            </div>
            <div class=""form-group"">
            <label for=""jiraemail"">Email address</label>
            <input type=""email"" class=""form-control"" id=""jiraemail""  placeholder=""Enter email"">
            </div>
            <div class=""form-group"">
            <label for=""apikey"">Api Key</label>
            <input type=""password"" class=""form-control"" id=""apikey"" placeholder=""Enter Api Key"">
            </div>
            <div class=""form-check"">
            <input type=""checkbox"" class=""form-check-input"" id=""exampleCheck1"">
            <label class=""form-check-label"" for=""exampleCheck1"">Check me out</label>
            </div>
            <button id = ""button"" type=""submit"" class=""btn btn-primary"" onclick=""myFunction"">Submit</button>
            </form>
            <script>
            function myFunction() {
            let jiralogincreds = '{""jiraurl"" : document.getElementById('jiraurl').innerText ,""jiraemail"" : document.getElementById('jiraemail').innerText ,""apikey"" : document.getElementById('apikey').innerText }' ;
            window.chrome.webview.postMessage(jiralogincreds);};
            </script>
            </body>
            </html>";
            return html;
        }

I want when the form opens and the user inputs the data into the fields and clicks the submit button for the data in those fields to be returned to my code.

After hours of research, I found that the webView21.CoreWebView2.WebMessageReceived component will do the trick, but I can't find out what I'm doing wrong and why my code is not catching anything. Any tips or answers are heavily appreciated, I've reached a dead end and I have spent more than 20 hours already trying to find a solution

Below is my full code:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JiraLogin
{
    public partial class JiraLoginWebView: Form
    {
        public JiraLoginWebView()
        {
            InitializeComponent();
            //InitializeAsync();

        }
        
        async void JiraLoginWebView_Load(object sender, EventArgs e)
        {
            //webView21.CoreWebView2InitializationCompleted += webView2_CoreWebView2InitializationCompleted;
            InitializeAsync();
        }
        private string getHtml()
        {
            string html = @"<html>
            <head>
            <link rel=""stylesheet"" href=""https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"" integrity=""sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"" crossorigin=""anonymous"">
            <script src=""https://code.jquery.com/jquery-3.3.1.slim.min.js"" integrity=""sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"" crossorigin=""anonymous""></script>
            <script src=""https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"" integrity=""sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"" crossorigin=""anonymous""></script>
            <script src=""https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"" integrity=""sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"" crossorigin=""anonymous""></script>
            </head>
            <body>
            <form>
            <div class=""form-group"">
            <label for=""jiraurl"">Jira Url</label>
            <input type=""url"" class=""form-control"" id=""jiraurl""  placeholder=""Enter Jira URL"">
            </div>
            <div class=""form-group"">
            <label for=""jiraemail"">Email address</label>
            <input type=""email"" class=""form-control"" id=""jiraemail""  placeholder=""Enter email"">
            </div>
            <div class=""form-group"">
            <label for=""apikey"">Api Key</label>
            <input type=""password"" class=""form-control"" id=""apikey"" placeholder=""Enter Api Key"">
            </div>
            <div class=""form-check"">
            <input type=""checkbox"" class=""form-check-input"" id=""exampleCheck1"">
            <label class=""form-check-label"" for=""exampleCheck1"">Check me out</label>
            </div>
            <button id = ""button"" type=""submit"" class=""btn btn-primary"" onclick=""myFunction"">Submit</button>
            </form>
            <script>
            function myFunction() {
            let jiralogincreds = '{""jiraurl"" : document.getElementById('jiraurl').innerText ,""jiraemail"" : document.getElementById('jiraemail').innerText ,""apikey"" : document.getElementById('apikey').innerText }' ;
            window.chrome.webview.postMessage(jiralogincreds);};
            </script>
            </body>
            </html>";
            return html;
        }


        private void WebView21_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
        {
  
            JiraLoginWebViewDTO jiraloginwebview = JsonConvert.DeserializeObject<JiraLoginWebViewDTO>(e.TryGetWebMessageAsString());
            
        }
        private async void InitializeAsync()
        {
            //await webView21.EnsureCoreWebView2Async(null);
            string html = getHtml();
            InitializeWebView2Async(html, "");
            

            //webView21.NavigateToString(html);
        }

        async void InitializeWebView2Async(string html, string tempDir = "")
        {
            CoreWebView2Environment webView2Environment = null;


            string tempDir2 = tempDir;

            if (String.IsNullOrEmpty(tempDir2))
            {

                tempDir2 = Path.GetTempPath();
            }
            CoreWebView2EnvironmentOptions options = null;


            webView2Environment = await CoreWebView2Environment.CreateAsync(null, tempDir2, options);

            await webView21.EnsureCoreWebView2Async(webView2Environment);
            webView21.NavigateToString(html);
            webView21.CoreWebView2.WebMessageReceived += WebView21_WebMessageReceived;





        }



    }

}

Upvotes: 0

Views: 5440

Answers (1)

amaitland
amaitland

Reputation: 4420

For those interested I've just released WebView2.DevTools.Dom to NuGet.org. It's free for anyone to use.

More details and examples in the Readme.

You can expose a function your JavaScript application can call.

await webView.EnsureCoreWebView2Async();

webView.CoreWebView2.DOMContentLoaded += async (s, e) =>
{
                var devToolsContext = await webView.CoreWebView2.CreateDevToolsContextAsync();
                
                await devToolsContext.ExposeFunctionAsync("jsButtonClick", () =>
                {
                    Dispatcher.InvokeAsync(() =>
                    {
                        WindowState = WindowState switch
                        {
                            WindowState.Maximized => WindowState.Normal,
                            WindowState.Normal => WindowState.Maximized,
                            _ => WindowState.Minimized,
                        };
                    });
                });
                

                var jsButton = await devToolsContext.QuerySelectorAsync("#jsButton");
                
                _ = jsButton.AddEventListenerAsync("click", "jsButtonClick");               
};

Functions persist across navigations so you only need to register a function once.

There's a working example available at https://github.com/ChromiumDotNet/WebView2.DevTools.Dom/blob/main/WebView2.DevTools.Dom.Wpf.Example/MainWindow.xaml.cs#L22

Upvotes: 2

Related Questions