Reputation: 8704
I have some content to read, loaded into webbrowser control. I want to see the progress while im reading. Is it possible to show vertical scrolling bar in webbrowser control somehow? Tried ScrollViewer.VerticalScrollVisibility
and putting entire webbrowser into ScrollViewer, nothing works!
Upvotes: 0
Views: 1114
Reputation: 181
Check out my solution basing on MisterGoodcat's idea. I've created a custom web browser control which injects the javascript after the page is loaded.
XAML:
<UserControl x:Class="Wallet.Views.Controls.WebBrowserWithScrollbar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid>
<phone:WebBrowser
Name="WebBrowserControl"
IsScriptEnabled="True"
Margin="0 0 5 0"
ScriptNotify="WebBrowser_OnScriptNotify">
</phone:WebBrowser>
<ScrollBar x:Name="DisplayScrollBar"
Orientation="Vertical"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Minimum="0"
Maximum="100"
Value="0"
Visibility="Collapsed"/>
</Grid>
Code behind:
/// <summary>
/// Adds a vertical scrollbar to the normal WebBrowser control
/// </summary>
public partial class WebBrowserWithScrollbar : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(string), typeof(WebBrowserWithScrollbar), new PropertyMetadata(string.Empty, OnSourcePropertyChanged));
#endregion
#region Fields
private int _visibleHeight;
private int _scrollHeight;
#endregion
#region Constructors
public WebBrowserWithScrollbar()
{
InitializeComponent();
this.LoadCompleted += this.WebBrowserControlLoadCompleted;
}
#endregion
#region Event Handlers
public event LoadCompletedEventHandler LoadCompleted
{
add
{
WebBrowserControl.LoadCompleted += value;
}
remove
{
WebBrowserControl.LoadCompleted -= value;
}
}
public event EventHandler<NotifyEventArgs> ScriptNotify
{
add
{
WebBrowserControl.ScriptNotify += value;
}
remove
{
WebBrowserControl.ScriptNotify -= value;
}
}
public event EventHandler<NavigationEventArgs> Navigated
{
add
{
WebBrowserControl.Navigated += value;
}
remove
{
WebBrowserControl.Navigated -= value;
}
}
public event EventHandler<NavigatingEventArgs> Navigating
{
add
{
WebBrowserControl.Navigating += value;
}
remove
{
WebBrowserControl.Navigating -= value;
}
}
public event NavigationFailedEventHandler NavigationFailed
{
add
{
WebBrowserControl.NavigationFailed += value;
}
remove
{
WebBrowserControl.NavigationFailed -= value;
}
}
#endregion
#region Properties
public string Source
{
get
{
return (string)this.GetValue(SourceProperty);
}
set
{
this.SetValue(SourceProperty, value);
}
}
#endregion
#region Static Methods
private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var controlWrapper = d as WebBrowserWithScrollbar;
if (controlWrapper != null)
{
var webBrowser = controlWrapper.WebBrowserControl;
var newSource = e.NewValue as string;
Uri uri;
if (webBrowser != null &&
newSource != null &&
e.NewValue != e.OldValue &&
!string.IsNullOrEmpty(newSource) &&
Uri.TryCreate(newSource, UriKind.Absolute, out uri))
{
webBrowser.Source = uri;
}
}
}
#endregion
#region Methods
private void WebBrowserControlLoadCompleted(object sender, NavigationEventArgs e)
{
this.InitializeScrollBarScript();
}
private void WebBrowser_OnScriptNotify(object sender, NotifyEventArgs e)
{
var parts = e.Value.Split('=');
if (parts.Length != 2)
{
return;
}
int number;
if (!int.TryParse(parts[1], out number))
{
return;
}
if (parts[0] == "scrollHeight")
{
_scrollHeight = number;
if (_visibleHeight > 0)
{
DisplayScrollBar.Maximum = _scrollHeight - _visibleHeight;
}
}
else if (parts[0] == "clientHeight")
{
_visibleHeight = number;
if (_scrollHeight > 0)
{
DisplayScrollBar.Maximum = _scrollHeight - _visibleHeight;
}
}
else if (parts[0] == "scrollTop")
{
DisplayScrollBar.Value = number;
}
this.DisplayScrollBar.Visibility = this._visibleHeight >= this._scrollHeight ? Visibility.Collapsed : Visibility.Visible;
}
private void InitializeScrollBarScript()
{
try
{
WebBrowserControl.InvokeScript(
"eval",
new[]
{
"function onScroll() { " + "var scrollPosition = document.body.scrollTop;"
+ "window.external.notify(\"scrollTop=\" + scrollPosition.toString());"
+ "window.external.notify(\"scrollHeight=\" + document.body.scrollHeight.toString());"
+ "window.external.notify(\"clientHeight=\" + document.body.clientHeight.toString()); } "
+ "window.external.notify(\"scrollHeight=\" + document.body.scrollHeight.toString());"
+ "window.external.notify(\"clientHeight=\" + document.body.clientHeight.toString()); "
+ "window.onscroll = onScroll"
});
}
catch (Exception xcp)
{
Debug.WriteLine("Exception occured while executing invoke script:");
Debug.WriteLine(xcp);
DisplayScrollBar.Visibility = Visibility.Collapsed;
}
}
#endregion
}
Upvotes: 1
Reputation: 8704
..Nobody is answering..
But ive already found the solution. Not quite ideal one and its a bit dirty, but it works and i can show reading progress now. http://www.pitorque.de/MisterGoodcat/post/Somethings-Missing-from-the-WebBrowser-Control.aspx the main idea is to inject some javascript into the page and notify browser about scrolling events; after that change the position of custom scrollbar control placed somewhere near the browser.
Upvotes: 0