Мое приложение WPF создает несколько элементов управления WebBrowser. Я знаю, как манипулировать HtmlDocument внутри каждого, а также как обрабатывать события мыши на них. Однако из события мыши, которое имеет объект IHTMLEventObj2 в качестве параметра, как я могу получить хостинг WebBrowse? Я могу получить доступ к документу через srcElement.document, но как мне «перейти вверх» к веб-браузеру, в котором размещен этот документ? Я думал об использовании свойства «Тег», но в HTMLDocument его нет. В крайнем случае я, вероятно, мог бы использовать хеш-таблицу на основе объекта HtmlDocument, но это немного сложно для такой простой вещи...
Как получить элемент управления WebBrowser из содержащегося в нем HTMLDocument в WPF?
Ответы (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, отправитель, аргументы);
не будет работать, так как каждый раз, когда эта строка выполняется, создается новый обработчик, совершенно не равный тому, который был создан с помощью +=