I used a those article to create AttachedProperty of Webbrowser control, so I can bind the “BindableSource” to my public property “Path”. It is great and work well with one small disadvantage. In my ViewModel constructor the property is set to:
Path = new Uri("http://microsoft.com");
When the p开发者_开发问答age is loaded I navigate to another link and “WebBrowser.Source” property is changed but “WebBrowser.BindableSource” is not changed. When I click a button which set again:
Path = new Uri("http://microsoft.com");
The “BindableSourcePropertyChanged” is not called because the property has those value.
I had an idea how to solve it but its not good, because slow the performance, It is to set Path to another URL and after that set it to real URL (http://microsoft.com).
Path = new Uri("http://google.com");
Path = new Uri("http://microsoft.com");
Can you give me please a better idea, how can I solved it. Thanks in advanced.
I propose to synchronize BindableSource with Navigated event. You coukld achieve this by exposing another one attached behaviour at your WebBrowserUtility class, that reacts on Navigated event like this:
public static readonly DependencyProperty ShouldHandleNavigatedProperty =
DependencyProperty.RegisterAttached(
"ShouldHandleNavigated",
typeof(Boolean),
typeof(WebBrowserUtility),
new UIPropertyMetadata(false, ShouldHandleNavigatedPropertyChanged));
public static Boolean GetShouldHandleNavigated(DependencyObject obj)
{
return (Boolean)obj.GetValue(BindableSourceProperty);
}
public static void SetShouldHandleNavigated(DependencyObject obj, Boolean value)
{
obj.SetValue(ShouldHandleNavigatedProperty, value);
}
public static void ShouldHandleNavigatedPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = o as WebBrowser;
if (browser != null)
{
if ((bool)e.NewValue)
{
browser.Navigated += new NavigatedEventHandler(Browser_Navigated);
}
else
{
browser.Navigated -= new NavigatedEventHandler(Browser_Navigated);
}
}
}
private static void Browser_Navigated(object sender, NavigationEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (browser != null)
{
browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
}
}
Usage in xaml:
<WebBrowser self:WebBrowserUtility.BindableSource="{Binding WebAddress}"
self:WebBrowserUtility.ShouldHandleNavigated="True"/>
P.S. I should admit that this implementation is rather dirty, because setting of BindableSource inside Navigated event handler forces one additional event fireing. But this code works, and you could consider about its improvement.
EDITED
public static class WebBrowserUtility
{
...
private const string _SkipSourceChange = "Skip";
public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = o as WebBrowser;
if (browser != null)
{
string uri = e.NewValue as string;
if (!_SkipSourceChange.Equals(browser.Tag))
{
browser.Source = uri != null ? new Uri(uri) : null;
}
}
}
private static void Browser_Navigated(object sender, NavigationEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (browser != null)
{
if (WebBrowserUtility.GetBindableSource(browser) != e.Uri.ToString())
{
browser.Tag = _SkipSourceChange;
browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
browser.Tag = null;
}
}
}
}
精彩评论