wpf中我想在WebBrowser控件上放置一个Border控件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wpf中我想在WebBrowser控件上放置一个Border控件相关的知识,希望对你有一定的参考价值。

wpf中我想在WebBrowser控件上放置一个Border控件但是总是被遮挡一直没有找到解决方案希望问问的大哥大姐们能够帮忙解决这个问题。

参考技术A 再开一个窗口,覆盖在有WebBrowser所在的窗口上,否则WebBrowser这类COM组件总是在WPF元素渲染完成后,才被渲染,因此,一个WPF窗口里的COM组件上不能覆盖WPF界面元素。

如何通过 MVVM 在 WPF WebBrowser 控件上使用 Javascript

【中文标题】如何通过 MVVM 在 WPF WebBrowser 控件上使用 Javascript【英文标题】:How to use Javascript on a WPF WebBrowser Control via MVVM 【发布时间】:2011-11-02 23:56:51 【问题描述】:

我在 WPF4 上使用 MVVM 模式,尽管我对这两种模式都是新手。我正在寻找一个很好的解决方案来使用可以接收 Javascript 命令并与 ViewModel 通信的 WebBrowser 控件。它需要以下内容:

    能够从 Javascript 表单中收集值并将其返回给 ViewModel 使用Javascript判断ReadyState之前 运行 Javascript 命令(设置表单值、将表单值用于逻辑步骤、提交表单)一些会在多个页面加载时发生

正在处理的网站不受我的控制,无法编辑或更新。它大量使用 ActiveX,并且不接受非 IE 浏览器(Awesomium 将不起作用),因此标准的 WPF WebBrowser 控件可能是唯一的选择。

This question 提供了一种将浏览器控件的源与附加属性绑定的解决方案。我认为这可以适用于使用导航方法发送 javascript,但我不确定如何将值返回到 Viewmodel。这是我需要克服的主要障碍。

重度编辑 - 问题的浏览量很低,没有答案,完全改写了

【问题讨论】:

重新成为你的旗帜:这超出了模组的能力。可以咨询Meta Stack Overflow。 奖励赏金的方式确实有点奇怪,您可能想将此作为 MSO 上的一个可能的错误提出。我不知道为什么它在仅仅六天后就被授予了。 Known (and fixed) bug。开发人员应该能够撤消赏金或类似的事情。 【参考方案1】:

如果您与网站开发人员合作为您的应用程序创建解决方案,那么您将使用ObjectForScripting 在 JavaScript 和应用程序之间进行通信。有一篇很好的文章here,还有一个可能有帮助的问题here。

但是,据我了解,该网站是一个任意第三方网站,与您的应用程序没有任何关联,您希望自动填写一些表单值并在您的代码中提交表单。

为此,您可以处理 WebBrowser 的 LoadCompleted 事件。当加载的文档readyState 更改为已完成时调用此方法。因此,您可以将此事件用作挂钩,然后设置/读取文档表单值。请注意,您需要在项目中添加对 Microsoft mshtml 的引用。

以下是一个 MVVM 样式 (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,但要获得对发送者的访问权限取决于您自己的实现。

【讨论】:

我可以看到如何使用它来获取值,但也可以使用此方法设置值,并通过javascript提交表单? 其实我对此有一个疑问,我是否必须使用附加行为将命令绑定到导航事件,或者有直接的方法吗? 是的,我认为您可以使用文档加载事件来调用 JavaScript 并发布表单。我还没试过。您将对事件使用附加行为。我认为 Prism 提供了另一种选择,但我已经有一段时间没有使用它了。 在 javascript 完成执行之前,html 渲染完成时不会发生文档加载事件吗?我将研究棱镜,看看它是否可以做到这一点。您的回答很有帮助,但我认为它并不完整。 WebBrowser 控件 DocumentLoaded 事件在控件完成下载内容并呈现页面时发生。它为您的问题的第 2 部分和第 3 部分提供了一个钩子。回到电脑前我会澄清(当你说 ReadyState 时,你是什么意思?)。 Prism 是一个用于构建 WPF 应用程序以分离关注点的框架(与客户端代码无关)。我不确定你是否在使用它。【参考方案2】:

我不知道为什么我以前从未想过,但解决方案似乎很简单。

不要在视图上使用&lt;WebBrowser> 控件,而是使用&lt;ContentControl&gt; 并将其内容绑定到 ViewModel 中的 WebBrowser 属性。在 ViewModel 的构造函数中创建 WebBrowser,然后您可以将浏览器的导航事件(或 documentloaded)注册到 ViewModel 中的事件中。

来自 ViewModel 的完全浏览器控制!您甚至可以捕获用户事件,因为他们为导航页面所做的任何事情都将被捕获到您的 ViewModel 的导航事件中。

【讨论】:

难以置信的解决方案! 很好,这帮助我解决了一个有点相关的问题,即必须为可绑定的 Source 和 ObjectForScripting 属性编写 DependencyProperties,其中脚本对象似乎无论如何都绑定得太晚了。现在我只有一个简单的 WebBrowser 构造函数,并且可以转储整个辅助类。

以上是关于wpf中我想在WebBrowser控件上放置一个Border控件的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 MVVM 在 WPF WebBrowser 控件上使用 Javascript

wpf 用cefsharp替代web控件

如何在 webbrowser WPF 顶部打开用户控件作为弹出窗口

WPF WebBrowser 浏览器版本

使用 WPF WebBrowser 控件时如何抑制脚本错误?

C# WPF WebBrowser控件调用Refresh()函数出现异常,导致程序“未响应”并无法继续运行