您的 ViewModel 应该完全不知道 View 或特定控件。是否保持你观点背后的代码清晰,是一个宗教问题。
If you want to keep it clean, which I recommend whenever possible, there are a number of concepts, which allow you to do so.
First, you need to design your View/ViewModel relationship in a way, that all data relevant for the ViewModel is present 'at all times' in the ViewModel or can be passed to the ViewModel via CommandParameter
of a ICommand
. In your case, if the page of the Webbrowser is controlled by (i.e. might be set from) the ViewModel, the ViewModel should hold a property, which is bound to the Source
property of the browser. If the ViewModel just needs to 'know' the Uri when the BrowserNavigated
is executed, just pass it as a CommandParameter
.
Navigated
其次,对于您的特定情况,您希望在引发 WebBrowser 事件时在 ViewModel 上执行命令。与往常一样,有多种选择。我更喜欢框架附带的选项:EventTrigger
inSystem.Windows.Interactivity
允许您通过绑定将任何控件的任何事件传递给命令。
这样,可以从 ViewModel 设置 Uri:
<WebBrowser Source="{Binding BrowserPageUri}" Name="wbGoogle">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Navigated" >
<i:InvokeCommandAction Command="{Binding BrowserNavigated}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</WebBrowser>
这样,您可以将 Uri 作为命令的参数处理:
<WebBrowser Name="wbGoogle">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Navigated" >
<i:InvokeCommandAction Command="{Binding BrowserNavigated}"
CommandParameter="{Binding Source, ElementName=wbGoogle}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</WebBrowser>
当然,这只允许您在 WebBrowser 中访问页面的 Uri,而不是页面本身。如果您需要绑定到页面对象本身,则需要使用附加属性扩展 WebBrowser,以使该Document
属性可绑定。这很简单:
WebBrowser 的附加文档属性
将此属性附加到您的 WebBrowser 后,您可以像在上面的代码中一样定义 WebBrowser 的绑定,只是使用附加的属性,而不是Source
属性。
请注意,绑定到附加属性的语法是:
{Binding Path=(WebBrowserExtentions.Document)}