databind the Source property of the WebBrowser in WPF
The problem is that WebBrowser.Source
is not a DependencyProperty
. One workaround would be to use some AttachedProperty
magic to enable this ability.
public static class WebBrowserUtility
{
public static readonly DependencyProperty BindableSourceProperty =
DependencyProperty.RegisterAttached("BindableSource", typeof(string), typeof(WebBrowserUtility), new UIPropertyMetadata(null, BindableSourcePropertyChanged));
public static string GetBindableSource(DependencyObject obj)
{
return (string) obj.GetValue(BindableSourceProperty);
}
public static void SetBindableSource(DependencyObject obj, string value)
{
obj.SetValue(BindableSourceProperty, value);
}
public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = o as WebBrowser;
if (browser != null)
{
string uri = e.NewValue as string;
browser.Source = !String.IsNullOrEmpty(uri) ? new Uri(uri) : null;
}
}
}
Then in your xaml do:
<WebBrowser ns:WebBrowserUtility.BindableSource="{Binding WebAddress}"/>
WebBrowser in WPF with bound Source attached property navigates only once
I just decided to create a new browser in a static border each time I need to navigate.
<Border Grid.Row="1" at:AttachedUri.AttachedUri="{Binding BrowserUri}"/>
And code:
public static void AttachedUriPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
Border border = o as Border;
if (border != null)
{
string uri = e.NewValue as string;
if (!String.IsNullOrEmpty(uri))
{
Uri link = new Uri(uri);
WebBrowser newBrowser = new WebBrowser();
newBrowser.Navigate(link);
border.Child = newBrowser;
}
}
}
Can I bind HTML to a WPF Web Browser Control?
See this question.
To summarize, first you create an Attached Property for WebBrowser
public class BrowserBehavior
{
public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached(
"Html",
typeof(string),
typeof(BrowserBehavior),
new FrameworkPropertyMetadata(OnHtmlChanged));
[AttachedPropertyBrowsableForType(typeof(WebBrowser))]
public static string GetHtml(WebBrowser d)
{
return (string)d.GetValue(HtmlProperty);
}
public static void SetHtml(WebBrowser d, string value)
{
d.SetValue(HtmlProperty, value);
}
static void OnHtmlChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
WebBrowser webBrowser = dependencyObject as WebBrowser;
if (webBrowser != null)
webBrowser.NavigateToString(e.NewValue as string ?? " ");
}
}
And then you can Bind to your html string and NavigateToString will be called everytime your html string changes
<WebBrowser local:BrowserBehavior.Html="{Binding MyHtmlString}" />
Is there an MVVM-friendly way to use the WebBrowser control in WPF?
I used this in my bindable webbrowser wrapper:
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));
Note that I created my bindable webbrowser as FrameworkElement that exposes DependencyProperties and calls methods on the actual browser element, so i can set CommandBindings on it.
That way, you can use the default NavigationCommands in your View.
The used handlers are:
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);
}
Related Topics
How to Disable a System Device Programmatically
.Net (C#): Getting Child Windows When You Only Have a Process Handle or Pid
Uploading Objects to Google Cloud Storage Buckets in C#
How to Initialize a List of Strings (List<String>) with Many String Values
How to Write Asynchronous Linq Query
Pattern for Calling Wcf Service Using Async/Await
What Is It That Makes Enum.Hasflag So Slow
How to Use Xpath with Xdocument
Encrypt Password in App.Config
I Didn't Find "Zipfile" Class in the "System.Io.Compression" Namespace
How Should Anonymous Types Be Used in C#
Event Bubbling and Mvp: ASP.NET
Wix - How to Run/Install Application Without Ui
Convert Bitmaps to One Multipage Tiff Image in .Net 2.0
What Is the Fastest Way I Can Compare Two Equal-Size Bitmaps to Determine Whether They Are Identical
Send Smtp Email Using System.Net.Mail via Exchange Online (Office 365)