Встроенное приложение Silverlight внутри .NET настольного приложения и связь между ними - PullRequest
1 голос
/ 08 февраля 2011

У меня есть приложение 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 с сообщением «Метод или операция не реализованы».Хорошо, это не может рассматриваться как динамическое, но что это тогда?Как вызвать любой метод для этого?

Ответы [ 2 ]

2 голосов
/ 08 февраля 2011

В настоящее время нет управляемого взаимодействия.Два варианта, которые вы упомянули (взаимодействие с JavaScript через мост DOM или хостинг COM), - это все, что существует.

Я очень рекомендую вам провести исследование - вы знали все, что я собирался сказать, когда я нажимал навопрос!

0 голосов
/ 08 февраля 2011

Я не совсем уверен, как вы будете передавать сложные структуры между вашим SL-приложением и хостом, но один из вариантов, который вы можете использовать при возбуждении событий, - это передача информации через URL. Присоедините обработчик события к событию WebBroswer.Navigated, и этот обработчик вызовет событие вашего хоста на основе информации в URL.

Например, у нас есть приложение Silverlight, которое размещено внутри элемента управления WPF WebBrowser. Мы хотели знать, когда пользователь нажимал кнопку «Закрыть» в приложении Silverlight. Мы прикрепили обработчик событий к WebBrowser.Navigated и проанализировали URL. Мы специально искали «closed = true» внутри этого URL. Если найдено, закройте все приложение (включая хост WPF).

Приложение Silverlight внутри WPF WebBrowser?

...