How to call C# method in javascript by using GeckoFX as the wrapper of XULRunner
Asked Answered
D

3

6

I am using GeckoFX16 and xulrunner-16.0.2.en-US.win32 in my project. The thing is, I want to call a C# method in javascript.

I am curious, is there a way to do this?

Just like below:

C# part:

private GeckoWebBrowser weBrowser;
    public browser()
    {
        InitializeComponent();
        Gecko.Xpcom.Initialize("xulrunner");
        weBrowser = new GeckoWebBrowser();
        weBrowser.Parent = this;
        weBrowser.Dock = DockStyle.Fill;
        weBrowser.Navigate("test.html");
    }

    public string loadData(){
        //load data from local file.
        return str;
    }

javascript part:

<script type='text/javascript'>
    var data = window.loadData();
    alert(data);
</script>

I am new in this area, I’ll appreciate if it is possible!

Daman answered 29/3, 2013 at 20:0 Comment(0)
P
6

You can use a MessageEvent to invoke code in c#, but as far as I know you can't then return a string like you're wanting to. One of the unit tests demonstrates how to invoke the c# code:

[Test]
public void AddEventListener_JScriptFiresEvent_ListenerIsCalledWithMessage()
{
    string payload = null;

    browser.AddMessageEventListener("callMe", ((string p) => payload = p));

    browser.LoadHtml(
        @"<!DOCTYPE html>
                     <html><head>
                     <script type='text/javascript'>
                        window.onload= function() {
                            event = document.createEvent('MessageEvent');
                            var origin = window.location.protocol + '//' + window.location.host;
                            event.initMessageEvent ('callMe', true, true, 'some data', origin, 1234, window, null);
                            document.dispatchEvent (event);
                        }
                    </script>
                    </head><body></body></html>");

    browser.NavigateFinishedNotifier.BlockUntilNavigationFinished();
    Assert.AreEqual("some data", payload);
}

I know it's awkward, but you could then use a c#-->javascript call to get data back to javascript-land. See This Question for how to do that. So your javascript would first send this message to c# land, then it would get a callback with the string value you need.

Hope that helps.

Premise answered 31/3, 2013 at 1:28 Comment(2)
BTW If you're like me, and call AddMessageEventListener at the same time as setting up other events (eg DocumentReady) you'll get a NullRefException, with little idea what's wrong. It looks like you need to call AddMessageEventListener after a certain unspecified time when it's good and ready.Heavyduty
A little bizarre that the syntax used is "((string p) =>" when "p =>" works perfectly fine.Heavyduty
L
7

Important update:

Currently code with event.initMessageEvent does not work because this construction has been replaced on

var event = new MessageEvent('yourEventName', { 'view': window, 'bubbles': false, 'cancelable': false, 'data': 'some data' });
Liminal answered 5/8, 2015 at 21:13 Comment(0)
P
6

You can use a MessageEvent to invoke code in c#, but as far as I know you can't then return a string like you're wanting to. One of the unit tests demonstrates how to invoke the c# code:

[Test]
public void AddEventListener_JScriptFiresEvent_ListenerIsCalledWithMessage()
{
    string payload = null;

    browser.AddMessageEventListener("callMe", ((string p) => payload = p));

    browser.LoadHtml(
        @"<!DOCTYPE html>
                     <html><head>
                     <script type='text/javascript'>
                        window.onload= function() {
                            event = document.createEvent('MessageEvent');
                            var origin = window.location.protocol + '//' + window.location.host;
                            event.initMessageEvent ('callMe', true, true, 'some data', origin, 1234, window, null);
                            document.dispatchEvent (event);
                        }
                    </script>
                    </head><body></body></html>");

    browser.NavigateFinishedNotifier.BlockUntilNavigationFinished();
    Assert.AreEqual("some data", payload);
}

I know it's awkward, but you could then use a c#-->javascript call to get data back to javascript-land. See This Question for how to do that. So your javascript would first send this message to c# land, then it would get a callback with the string value you need.

Hope that helps.

Premise answered 31/3, 2013 at 1:28 Comment(2)
BTW If you're like me, and call AddMessageEventListener at the same time as setting up other events (eg DocumentReady) you'll get a NullRefException, with little idea what's wrong. It looks like you need to call AddMessageEventListener after a certain unspecified time when it's good and ready.Heavyduty
A little bizarre that the syntax used is "((string p) =>" when "p =>" works perfectly fine.Heavyduty
O
2

You can add message event listener to your web browser and call your method like this:

private void load()
{
    browser.AddMessageEventListener("myFunction", ((string s) => this.showMessage(s)));
    browser.LoadHtml
    (
        @"<!DOCTYPE html>
          <html><head>                 
          <meta http-equiv=""Content-Type"" content=""text/html; charset=UTF-8"">
          <script type=""text/javascript"">
             function fireEvent(name, data)
             {
                event = document.createEvent('MessageEvent');
                event.initMessageEvent(name, false, false, data, null, null, null, null);
                document.dispatchEvent(event);
             }                        
          </script>
          </head>
          <body>
             <input type=""button"" onclick=""fireEvent('myFunction', 'some data');"" value=""SHOW DATA"" />
          </body></html>"
    );
}

...

private void showMessage(string s)
{
    MessageBox.Show(s);
}    

Now you can add more msg events to your msg listener (if you need to) and fire them all in the same way.

Outshine answered 6/6, 2013 at 13:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.