QA@IT

VB.netのWebBrowserコントロールで動的に追加したボタンのonClickが動作しない

768 PV

VB2013を使用しています。
WebBrowserコントロールをFormに配置しtest.htmlを読み込ませました。
DocumentCompletedイベントでボタンを動的に追加させたのですが、追加したボタンのonClickが動作しません。
onClickの動作は外部のjsファイルに書いており、test.htmlに元からあるボタンでは動作します。
追加したボタンのonClickを動作させるには、どのようにすれば良いでしょうか?

VB

Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
    WebBrowser1.Navigate("file:///C:/TEST/test.html")
End Sub

Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
    Dim doc As HtmlDocument = WebBrowser1.Document

    Dim element As HtmlElement = doc.CreateElement("input")
    element.SetAttribute("type", "button")
    element.SetAttribute("value", "クリック")
    element.SetAttribute("onclick", "testClick()")

    doc.GetElementsByTagName("div")(1).AppendChild(element)
End Sub

test.html

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script language="javascript" src="func.js"></script>
</head>
<body>
<div><input type="button" value="click" onClick="testClick()"/></div>
<div></div>
</body>
</html>

func.js

function testClick() {
    alert("click!");
}
  • ボタンをクリックするのは C# のコードで行いたいのか、WebBrowser 上にボタンが表示された後ユーザーがクリックするのか、どちらですか? -

回答

WebBrowser 上にボタンが表示された後ユーザーがクリックするのであろうと理解して、ちょっと試してみましたが、質問者さんのコードの、

element.SetAttribute("onclick", "testClick()")

ではイベントにリスナをアタッチできないようです。(試したのは C# ですが VB.NET も同じはず)

デバッガで調べると html には確かに反映されているのですが、当該ボタンをクリックしてもアタッチされているはずのリスナは動きません。

画像の上の赤枠が静的に配置した input 要素、下の赤枠が C# のコードで動的に配置し SetAttribute メソッドで onclick 属性を設定したものです。見たところ同じですが、上は動くものの、下はダメです。

webbrowser.jpg

ちなみに、JavaScript で設定してもデフォルトの WebBrowser(IE7 相当)では、

element.setAttribute("onclick", "listener()");

ではダメで、以下のようにする必要があります。

if (element.addEventListener) {
    element.addEventListener('click', listener, false);
} else if (element.attachEvent) {
    element.attachEvent('onclick', listener);
}

レジストリを書き換えて IE11 相当で WebBrowser が動くようにすれば、JavaScript の方は setAttribute で設定して動くようになりますが、.NET の方は SetAttribute による設定では依然としてダメでした。

以上の結果から、想像ですが、JavaScript の setAttribute は新しいバージョンの IE であればイベントへのリスナのアタッチもできるようにアップデートしたが、WebBrowser で使う HtmlElement の SetAttribute の方は以前のままサポートしてないということのように思えます。

.NET の HtmlElement クラスでは JavaScript の addEventListener のようなメソッドは利用できないので、自分が考え付く手段は、目的の div 要素の HtmlElement 取得したら、その InnerHtml に以下のように input 要素を書き込むことぐらいです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WebBrowser2
{
    public partial class Form1 : Form
    {
        private string url = "http://websiteproject.com/0064-WebBrowserTest.aspx";

        public Form1()
        {
            InitializeComponent();
            this.textBox1.Text = this.url;
        }

        private void navigateButton_Click(object sender, EventArgs e)
        {
            this.webBrowser1.Navigate(this.textBox1.Text);
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            HtmlDocument document = this.webBrowser1.Document;

            // これはダメ。イベントにリスナをアタッチできない
            //HtmlElement element = document.CreateElement("input");
            //element.SetAttribute("type", "button");
            //element.SetAttribute("value", "C#で追加");
            //element.SetAttribute("onclick", "listenerForButton2()");
            //document.GetElementById("div1").AppendChild(element);

            // デバッグ用
            HtmlElementCollection elements = document.GetElementsByTagName("div");

            document.GetElementById("div1").InnerHtml = "<input type=\"button\" value=\"C#で追加\" onclick=\"listenerForButton2()\" />";
        }
    }
}

これで当該ボタンをクリックすれば以下の通りリスナは動きます。

result.jpg

編集 履歴 (0)
  • WebBrowser上で.NETから動的に追加したボタンをクリックしたとき、元からあるボタンと同じ動作をさせようとしていました。

    InnerHtmlで追加するは思いつきませんでした。
    SetAttributeがあるもんだから、これで何とかするんだと思い込んでいました。

    自分のプログラムも同じように組み込み、動作することを確認できました。
    ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。