Подтвердить что ты не робот

Как использовать Javascript в WPF WebBrowser Control через MVVM

Я использую шаблон MVVM на WPF4, хотя я новичок в обоих. Я ищу хорошее решение для использования элемента управления WebBrowser, который может получать команды Javascript и общаться с ViewModel. Он нуждается в следующем:

  • Возможность собирать значения из форм Javascript и возвращать их в ViewModel
  • Используйте Javascript для определения ReadyState до
  • Выполнение команд Javascript (установка значений формы, использование значений форм для логических шагов, отправка формы), которые происходят при загрузке нескольких страниц.

Работающий сайт не под моим контролем для редактирования или обновления. Он активно использует ActiveX и не принимает браузеры, отличные от IE (Awesomium не будет работать), поэтому стандартный элемент управления WPF WebBrowser, вероятно, единственный вариант.

Этот вопрос предоставляет решение для привязки источника контроля браузера с прикрепленным свойством. Я думаю, что это может быть адаптировано для использования метода навигации для отправки javascript, хотя я не уверен, как значения могут быть возвращены в Viewmodel. Это главное препятствие, которое мне нужно преодолеть.

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

4b9b3361

Ответ 1

Хорошо, если вы работали с разработчиками сайта для создания решения для своего приложения, вы использовали бы ObjectForScripting для связи между JavaScript и приложением. Там хорошая статья здесь, и еще один вопрос, который может быть полезен здесь.

Однако, насколько я понимаю ваш вопрос, сайт является произвольным сторонним сайтом, не связанным с вашим приложением, и вы хотите автоматически заполнить некоторые значения формы и отправить форму в свой код.

Для этого вы можете обработать событие LoadCompleted для WebBrowser. Это вызывается, когда загруженный документ readyState изменяется на завершенный. Поэтому вы можете использовать это событие как крючок, чтобы затем установить/прочитать значения формы документа. Обратите внимание, что вам нужно будет добавить ссылку на Microsoft mshtml в проекте.

Ниже приведена команда MVVM style (PRISM), которая позволяет событию напрямую связываться с ViewModel с использованием поведения. Это эквивалентно регистрации обработчика события в коде.

public ICommand LoadCompleted
{
    get
    {
        return new EventToCommandWithSender<NavigationEventArgs>(
            (s,e) => { 

               WebBrowser browser = (WebBrowser) sender;
               // false if nested frame
               if (e.IsNavigationInitiator)
               {
                   mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)browser.Document;
                   // always completed
                   var readyState = doc.readyState;
                   // populate form
                   var name = doc.body.document.getElementById("username");
                   name.value = "@TheCodeKing";
                   // submit form
                   var submit = doc.body.document.getElementById("submit");
                   submit.Click();
                }
        });
    }
}

К сожалению, NavigationEventArgs не предоставляет способ доступа к HTML-документу или запросам данных. Он содержит свойство WebRequest, но это не было реализовано и всегда будет нулевым. В моем примере я принял пользовательский класс EventToCommandWithSender, который отправляет отправителю, а также ARG-события в случае возникновения события, но до вашей собственной реализации, чтобы получить доступ к отправителю.

Ответ 2

Я не знаю, почему это мне никогда не приходило в голову, но решение кажется таким простым.

Вместо того, чтобы иметь элемент управления <WebBrowser > в представлении, используйте <ContentControl> и привяжите его содержимое к свойству WebBrowser в ViewModel. Создайте WebBrowser в своем конструкторе ViewModel, а затем вы можете зарегистрировать событие навигации браузера (или загруженное документами) в событие в вашей ViewModel.

Полный контроль браузера из ViewModel! Вы даже можете захватывать пользовательские события, поскольку все, что они делают для навигации по странице, будет захвачено в вашем навигационном событии ViewModel.