C# and WebBrowser component question

F

Fawzib Rojas

I have an app with a WebBrowser component and I'm setting the the
ObjectForScripting component so the object can be used from javascript.

The object has a Scripting.Dictionary property. My problem is that in
javascript I have to use "external.dictionary.Item('x')" to get the
items instead of "external.dictionary('x')". If I create the
Scripting.Dictionary in javascript it works ok. For example:

Javascript:

var dict=new ActiveXObject( 'Scripting.Dictionary' );

dict.Add("item1","test");
external.dictionary.Add("item1","test");
alert(dict("item1"));
alert(external.dictionary("item1")); // this fails

alert(external.dictionary.Item("item")); / this works

What can I do so the dictionaries created by C# work the same as the
Javascript created ones?
 
N

Nicholas Paldino [.NET/C# MVP]

Fawzib,

Can you show the C# code which sets the ObjectForScripting? My guess is
that you are using a Dictionary<TKey, TValue> which then uses the
IDictionary interface (the only one marked as ComVisible).

If you want to use a .NET Dictionary<TKey, TValue> and still expose it
like a Scripting.Dictionary in the browser, then you either have to use a
Scripting.Dictionary in your app, and pass that, or, you can create a
wrapper class which implements the Scripting.Dictionary interface (it is a
COM object, so it has an interface) and then takes your .NET dictionary
instance and forwards the calls.
 
F

Fawzib Rojas

Nicholas said:
Fawzib,

Can you show the C# code which sets the ObjectForScripting? My guess is
that you are using a Dictionary<TKey, TValue> which then uses the
IDictionary interface (the only one marked as ComVisible).

If you want to use a .NET Dictionary<TKey, TValue> and still expose it
like a Scripting.Dictionary in the browser, then you either have to use a
Scripting.Dictionary in your app, and pass that, or, you can create a
wrapper class which implements the Scripting.Dictionary interface (it is a
COM object, so it has an interface) and then takes your .NET dictionary
instance and forwards the calls.

I don't see why I cant access the dictionary created in C# the same way
as a Javascript created one. Here is the class (removed most of the
irrelevant info):

public class MyExternal {
//
object m_globals = null;
//
public MyExternal(object gl) {
m_globals = gl;
}
public object globals {
get{
return(m_globals);
}
}
}

public partial class MainForm : Form {
// originally it was:
// Scripting.Dictionary globals=new Scripting.Dictionary();
// changed it because it didn't work either
MyExternal m_external;
//
object globals = Activator.CreateInstance(
Type.GetTypeFromProgID("Scripting.Dictionary")
);
//
public MainForm() {
InitializeComponent();
m_external=new MyExternal(globals);
AddValue(globals, "test", "test information");
MainBrowser.ObjectForScripting = m_external;
}
public void AddValue(object d, object k, object v) {
((Scripting.Dictionary)d).Add(ref k,ref v);
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Fawzib,

You need to use the DictionaryClass which is imported through TLBIMP.
The DictionaryClass implements the dispatch interface (which is necessary
for accessing the default property through script) whereas Dictionary and
IDictionary do not.

Change the type you expose to DictionaryClass and it should work.
 
F

Fawzib Rojas

Nicholas said:
Fawzib,

You need to use the DictionaryClass which is imported through TLBIMP.
The DictionaryClass implements the dispatch interface (which is necessary
for accessing the default property through script) whereas Dictionary and
IDictionary do not.

Change the type you expose to DictionaryClass and it should work.

Nope, it didn't work. I tried using DictionaryClass *and* IDictionary. I
made a minimalistic project if you want I could put it somewhere. Anyway
the code is like this:

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace TestDictionary {
public partial class Form1 : Form {
MyExternal m_external = new MyExternal();
string cwd = Path.GetDirectoryName(Application.ExecutablePath);
//
public Form1() {
InitializeComponent();
webBrowser1.ObjectForScripting = m_external;
}

private void Form1_Load(object sender, EventArgs e) {
webBrowser1.Navigate("file://"+cwd+"/TestDictionary.htm");
}
}

[ComVisible(true)]
public class MyExternal {
Scripting.IDictionary m_dict = new Scripting.DictionaryClass();
//
public Scripting.IDictionary dict {
get {
return m_dict;
}
}
}
}

TestDictionary.htm:

<html>
<head>
<script type="text/javascript">
document.local=new ActiveXObject( 'Scripting.Dictionary' );
document.local.Add("item","document.local works");
external.dict.Add("item","external.dict works");
// test C# dictionary
function test_dict1(){
alert(external.dict("item"));
}
// test C# dictionary (uses Item function)
function test_dict2(){
alert(external.dict.Item("item"));
}
// test JS dictionary
function test_dict3(){
alert(document.local("item"));
}
</script>
</head>
<body>
Use external.dict("item")<br>
<button onclick="test_dict1()">Test</button><br><br>
Use external.dict.Item("item")<br>
<button onclick="test_dict2()">Test</button><br><br>
Use document.local("item")<br>
<button onclick="test_dict3()">Test</button><br><br>
</body>
</html>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top