У меня есть приложение WPF.Мне нужно встроить в него приложение Silverlight.Как я понимаю, наиболее распространенный способ сделать это - использовать элемент управления System.Windows.Controls.WebBrowser (примечание: мое приложение - это wpf, а не WinForms).
Кстати: есть еще один способ разместить приложение Silverlight - использовать его COMинтерфейс (см. http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx).
Так что в моем приложении WPF у меня есть где-то WebBrowser:
<WebBrowser x:Name="webBrowser">
, где я загружаю свою HTML-страницу (давайте для простоты предположим, что локальная htlm-страница):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
webBrowser.LoadCompleted += WebBrowser_LoadCompleted;
webBrowser.Navigate(new Uri(Path.GetFullPath("HostPage.htm")));
}
private void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
MessageBox.Show("Silverlight app has loaded");
}
Хорошо. Это просто.
Теперь я хочу общаться с хостом из SL-приложения и с SL-приложением с хоста.
Я понимаю техникудля взаимодействия между HTML (JS) и Silverlight (http://msdn.microsoft.com/en-us/library/cc645076%28VS.95%29.aspx) и между .NET и JS внутри WebBrowser.
Я могу настроить WebBrowser.ObjectForScripting с объектом (помеченным ComVisibleAttribute), и объект будет получать доступв JS.
Я даже могу получить ссылку на этот объект из моего встроенного приложения Silverlight:
(ScriptObject) HtmlPage.Window.GetProperty("external");
Я также могу сделать некоторый объект внутри приложения Silverlight видимым для JS (и, возможно,для размещения кода) через HtmlPage.RegisterScriptableObject ("name", anObject);
Но.Проблема в том, что во всех случаях мне приходится иметь дело с некоторыми нетипизированными экземплярами ScriptObject.Но я бы хотел настроить связь «полностью управляемого кода» между хостом и SL-приложением.Я имею в виду прохождение сложных структур / классов / делегатов, создание событий и т. Д., То есть без каких-либо «нетипизированных JS-вещей».
Как я могу это сделать?
ОБНОВЛЕНИЕ : ладно, похоже, что нет хорошего способа сделать то, что я хочу.Поэтому мне приходится иметь дело с JS-совместимостью.Но здесь у меня проблема.С хоста я настроил ObjectForScripting и SL-приложение может его использовать.Это означает, что SL-приложение получает результаты от методов объекта, настроенного в WebBrowser.ObjectForScripting:
((ScriptObject) HtmlPage.Window.GetProperty("external")).Invoke("methodName")
Но не наоборот.В моем SL-приложении я регистрирую объект (типа BridgeSl):
m_bridgeSl = new BridgeSl();
HtmlPage.RegisterScriptableObject("bridge", m_bridgeSl);
Затем создаю JS-функцию в html:
<script type="text/javascript">
var g_bridgeSl = null;
function pluginLoaded(sender, args) {
g_bridgeSl = sender.getHost().Content.bridge;
}
</script>
, где pluginLoaded - обработчик onLoad плагина SL.event:
<object id="slCtrl" data="data:application/x-silverlight-2," type="application/x-silverlight-2" ...>
<param name="onLoad" value="pluginLoaded" />
</object>
Затем добавьте функцию, возвращающую этот объект:
function getBridge() {
return g_bridgeSl;
}
Я сделал все это, надеясь, что смогу получить экземпляр BridgeSl внутри моего хост-приложения:
var bridgeSl = WebBrowser.InvokeScript("getBridge");
На самом деле я что-то понимаю.Это экземпляр "System .__ ComObject".Но когда я приведу его к динамическому:
dynamic dynBridgeSl = bridgeSl;
, я получаю объект System.SystemException с сообщением «Метод или операция не реализованы».Хорошо, это не может рассматриваться как динамическое, но что это тогда?Как вызвать любой метод для этого?