Как получить элемент управления WebBrowser из содержащегося в нем HTMLDocument в WPF?

Мое приложение WPF создает несколько элементов управления WebBrowser. Я знаю, как манипулировать HtmlDocument внутри каждого, а также как обрабатывать события мыши на них. Однако из события мыши, которое имеет объект IHTMLEventObj2 в качестве параметра, как я могу получить хостинг WebBrowse? Я могу получить доступ к документу через srcElement.document, но как мне «перейти вверх» к веб-браузеру, в котором размещен этот документ? Я думал об использовании свойства «Тег», но в HTMLDocument его нет. В крайнем случае я, вероятно, мог бы использовать хеш-таблицу на основе объекта HtmlDocument, но это немного сложно для такой простой вещи...


person Franck Dervaux    schedule 09.08.2015    source источник


Ответы (1)


Где/как вы получаете событие мыши и srcElement.document? Это похоже на джаваскрипт.

Если это правда, то я почти уверен, что вы не можете получить доступ к веб-элементу управления из JavaScript, потому что веб-элемент управления не отображается в дереве DOM. Вы можете попробовать использовать window.external (или аналогичный) и выставить через него методы, а затем заставить методы работать в веб-браузере, но это было бы немного запутанно, но я уверен, что таким образом это возможно.

Если это не так и если у вас есть обработчик событий мыши на C#, просто свяжите обработчик с веб-браузером до вызова события. Вместо:

// inside your Window/etc:

private int otherData;
private void MyHandler(...args) {
    if(otherData > 5)
        browser.Navigate("foobar.html");
}

WebBrowser wb = ...;
wb.themouseevent += myhandler; // equivalent to wb.themouseevent += this.myhandler;

используйте замыкания или пользовательские объекты, чтобы открыть обработчик объекта, который заранее «знает» браузер:

// inside or outside your Window/etc:
class MyHandlersWithSomeData
{
    public WebBrowser browser;
    public string someContextuaData;
    public int otherData;
    ....

    public void MyHandler(...args) {
        if(otherData > 5)
            browser.Navigate("foobar.html");
    }
}

// inside your Window/etc:
WebBrowser wb = ...;
var smartHandler = new MyHandlersWithSomeData{ browser = wb, otherData = 10 };
wb.themouseevent += smartHandler.MyHandler; // note that handler is not from "this" anymore

редактировать: как вы просили, "более простой" подход заключался бы в использовании лямбда-выражений и замыканий:

// inside your Window/etc:

private int otherData;
private void JustAMethodNotAHandler(WebBrowser browser, object sender, EventArgs args) {
    if(otherData > 5)
        browser.Navigate("foobar.html");
}

WebBrowser wb = ...;
wb.themouseevent += (sender, args) => JustAMethodNotAHandler(wb, sender, args);

Однако никакой магии нет. Под капотом он делает это почти так же, как в примере выше, с дополнительным классом, так называемым «замыканием». Этот класс будет хранить ссылку на локальную переменную WebBrowser wb, и только благодаря этому при последующем вызове JustAMethodNotAHandler wb по-прежнему доступна и может быть передана этому методу.

Однако, поскольку теперь мы используем лямбда-выражения (синтаксис (blah)=>blah) для быстрого создания делегата, вы должны обратить внимание на две очень важные вещи:

  • JustAMethodNotAHandler это не обработчик, это просто метод. Анонимная функция, созданная лямбдой, будет фактическим обработчиком.
  • поскольку анонимная функция, ну, анонимная, вам будет нелегко, если вы когда-нибудь захотите отменить регистрацию ее позже. Такие попытки:

    wb.themouseevent -= (отправитель, аргументы) => JustAMethodNotAHandler(wb, отправитель, аргументы);

не будет работать, так как каждый раз, когда эта строка выполняется, создается новый обработчик, совершенно не равный тому, который был создан с помощью +=

person quetzalcoatl    schedule 09.08.2015
comment
Я обрабатываю события в С#. Я вижу, как это работает, но это немного сложно, так как требует определения нового класса обработчика. Любое более простое решение? - person Franck Dervaux; 09.08.2015