感谢this question (click me!),我的Source
属性的WebBrowser
属性正确绑定到我的ViewModel。
现在我想再实现两个目标:
IsEnabled
属性,以正确绑定CanGoBack
的{{1}}和CanGoForward
属性。WebBrowser
和GoForward()
方法,而无需使用代码隐藏且ViewModel不必了解GoBack()
。我现在有以下(非工作)XAML标记:
WebBrowser
我很确定问题是<WebBrowser
x:Name="_instructionsWebBrowser"
x:FieldModifier="private"
clwm:WebBrowserUtility.AttachedSource="{Binding InstructionsSource}" />
<Button
Style="{StaticResource Button_Style}"
Grid.Column="2"
IsEnabled="{Binding ElementName=_instructionsWebBrowser, Path=CanGoBack}"
Command="{Binding GoBackCommand}"
Content="< Back" />
<Button
Style="{StaticResource Button_Style}"
Grid.Column="4"
IsEnabled="{Binding ElementName=_instructionsWebBrowser, Path=CanGoForward}"
Command="{Binding GoForwardCommand}"
Content="Forward >" />
和CanGoBack
不是依赖属性(并且没有实现CanGoForward
),但我不太确定如何获取在那附近。
问题:
有没有办法连接附加的属性(就像我使用INotifyChanged
)或类似的东西来使Source
和CanGoBack
绑定起作用?
如何编写CanGoForward
和GoBackCommand
以便它们独立于代码隐藏和ViewModel并且可以在标记中声明?
答案 0 :(得分:4)
我在可绑定的webbrowser包装器中使用了它:
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseBack, BrowseBack, CanBrowseBack));
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseForward, BrowseForward, CanBrowseForward));
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseHome, GoHome, TrueCanExecute));
CommandBindings.Add(new CommandBinding(NavigationCommands.Refresh, Refresh, TrueCanExecute));
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseStop, Stop, TrueCanExecute));
请注意,我创建了我的可绑定webbrowser作为FrameworkElement,它公开DependencyProperties并在实际的浏览器元素上调用方法,所以我可以在其上设置CommandBindings。
这样,您可以在视图中使用默认的NavigationCommands。 使用过的处理程序是:
private void CanBrowseBack(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = webBrowser.CanGoBack;
}
private void BrowseBack(object sender, ExecutedRoutedEventArgs e) {
webBrowser.GoBack();
}
private void CanBrowseForward(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = webBrowser.CanGoForward;
}
private void BrowseForward(object sender, ExecutedRoutedEventArgs e) {
webBrowser.GoForward();
}
private void TrueCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; }
private void Refresh(object sender, ExecutedRoutedEventArgs e) {
try { webBrowser.Refresh(); }
catch (Exception ex) { PmsLog.LogException(ex, true); }
}
private void Stop(object sender, ExecutedRoutedEventArgs e) {
mshtml.IHTMLDocument2 doc = WebBrowser.Document as mshtml.IHTMLDocument2;
if (doc != null)
doc.execCommand("Stop", true, null);
}
private void GoHome(object sender, ExecutedRoutedEventArgs e) {
Source = new Uri(Home);
}
答案 1 :(得分:4)
对于遇到这个问题而想要一个完整解决方案的人来说,就是这样。它结合了该线程和链接线程(以及其他链接线程)中提出的所有建议。
XAML: http://pastebin.com/aED9pvW8
C#类: http://pastebin.com/n6cW9ZBB
示例XAML用法: http://pastebin.com/JpuNrFq8
注意:该示例假定您的视图绑定到提供浏览器源URL的ViewModel。一个非常基本的导航栏,带有后退,前进和刷新按钮以及地址栏,仅供演示。
享受。我已经将那些pastebin的到期时间设置为never,因此只要存在pastebin,它们就应该可用。
答案 2 :(得分:0)
您的问题似乎暗示,为了正确实现MVVM模式,您不能拥有任何代码隐藏。但是,在您的视图中添加一些代码隐藏可能会更容易将其与视图模型联系起来。您可以向视图添加依赖项属性,并让它监听INotifyPropertyChanged
个事件。