Есть ли MVVM-дружественный способ использовать элемент управления WebBrowser в WPF?

спасибо этот вопрос (нажми на меня!), я Source свойство my WebBrowser правильно привязка к моей ViewModel.

теперь я хотел бы достичь еще двух целей:

  1. скачать IsEnabled свойство моих кнопок Назад и вперед для правильной привязки к CanGoBack и CanGoForward свойства WebBrowser.
  2. выяснить, как вызвать GoForward() и GoBack() методы без прибегать к Код-за и без ViewModel должен знать о WebBrowser.

на данный момент у меня есть следующая (нерабочая) разметка XAML:

<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="&lt; Back" />

<Button
    Style="{StaticResource Button_Style}"
    Grid.Column="4"
    IsEnabled="{Binding ElementName=_instructionsWebBrowser, Path=CanGoForward}"
    Command="{Binding GoForwardCommand}"
    Content="Forward &gt;" />

я уверен, что проблема в том, что CanGoBack и CanGoForward не являются свойствами зависимостей (и не реализовать INotifyChanged), но я не совсем уверен, как обойти это.

вопросы:

  1. есть ли способ подключить вложенные свойства (как я сделал с Source) или что-то похожее, чтобы получить CanGoBack и CanGoForward привязки к работе?

  2. как писать GoBackCommand и GoForwardCommand таким образом, они не зависят от кода и ViewModel и могут быть объявлены в разметке?

3 ответов


я использовал это в моей bindable оболочке 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));

обратите внимание, что я создал свой bindable 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);
}

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

в XAML: http://pastebin.com/aED9pvW8

C# - класс : http://pastebin.com/n6cW9ZBB

пример использования XAML : http://pastebin.com/JpuNrFq8

Примечание: пример предполагает, что ваше представление привязывается к ViewModel это предоставляет исходный URL-адрес браузера. Очень рудиментарная панель навигации с Назад, Вперед, и кнопки обновления и адресной строки предоставляется только для демонстрации.

наслаждайтесь. Я установил срок годности этих пастебинов на никогда, поэтому они должны быть доступны до тех пор, пока существует пастебин.


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