Scrollable Webview with auto-height for WinRT
- Add the files (.cs and .xaml) to your existing solution.
MIT
<UserControl x:Class="UserControls.WebView.AdaptativeWebView" | |
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" | |
mc:Ignorable="d" | |
d:DesignHeight="300" | |
d:DesignWidth="400" | |
x:Name="Self"> | |
<Grid Background="{Binding Background, ElementName=Self}"> | |
<ScrollViewer> | |
<Grid Height="Auto"> | |
<WebView x:Name="WebviewContent" | |
VerticalAlignment="Top" | |
DefaultBackgroundColor="Transparent" /> | |
<Rectangle Height="{Binding Height, ElementName=WebviewContent}" | |
Name="RecWeb" | |
VerticalAlignment="Top" | |
Fill="#00000000" | |
Tapped="RecWebTapped" /> | |
</Grid> | |
</ScrollViewer> | |
</Grid> | |
</UserControl> |
namespace UserControls.WebView | |
{ | |
using System; | |
using Windows.UI.Xaml; | |
using Windows.UI.Xaml.Controls; | |
using Windows.UI.Xaml.Input; | |
public sealed partial class AdaptativeWebView : UserControl | |
{ | |
#region Static Fields | |
// Using a DependencyProperty as the backing store for WebView. This enables animation, styling, binding, etc... | |
public static readonly DependencyProperty WebViewProperty = | |
DependencyProperty.Register("WebView", typeof(WebView), typeof(AdaptativeWebView), new PropertyMetadata(null)); | |
#endregion | |
#region Constructors and Destructors | |
public AdaptativeWebView() | |
{ | |
this.InitializeComponent(); | |
this.WebView = this.WebviewContent; | |
this.WebviewContent.ScriptNotify += this.WebviewContentScriptNotify; | |
} | |
#endregion | |
#region Public Properties | |
public WebView WebView | |
{ | |
get | |
{ | |
return (WebView)this.GetValue(WebViewProperty); | |
} | |
set | |
{ | |
this.SetValue(WebViewProperty, value); | |
} | |
} | |
#endregion | |
#region Public Methods and Operators | |
public void NavigateToContent(string html, string styles = "", string scripts = "", int padding = 10) | |
{ | |
this.WebviewContent.NavigateToString(GenerateHtml(html, styles, scripts, padding)); | |
} | |
#endregion | |
#region Methods | |
private static string GenerateHtml(string html, string styles, string scripts, int padding) | |
{ | |
return @"<html> | |
<head> | |
<meta name=""viewport"" content=""width=device-width, initial-scale=1, user-scalable=no"" /> | |
<script type=""text/javascript""> | |
document.addEventListener('click', function(e) { | |
e = e || window.event; | |
var target = e.target || e.srcElement; | |
if(target.nodeName === 'A'){ | |
target.className += ' font-bold'; | |
setTimeout(function() {target.className -= ' font-bold'; }, 200); | |
} | |
}, false); | |
function loadLink(x,y){ | |
var el = document.elementFromPoint(x, y); | |
el && el.click(); | |
}; | |
function getDocHeight(id) { | |
var D = document; | |
return Math.max( | |
Math.max(document.getElementById(id).scrollHeight, document.getElementById(id).scrollHeight), | |
Math.max(document.getElementById(id).offsetHeight, document.getElementById(id).offsetHeight), | |
Math.max(document.getElementById(id).clientHeight, document.getElementById(id).clientHeight) | |
); | |
}; | |
function notifyDocumentHeightChanged(id){ | |
window.external.notify('rendered_height='+getDocHeight(id)); | |
}; | |
</script> | |
<style> | |
body { padding: " + padding + @"px; } | |
.font-bold { text-decoration: underline; } | |
a:active { text-decoration: underline;} | |
</style> | |
" + styles + @" | |
" + scripts + @" | |
</head> | |
<body onload='notifyDocumentHeightChanged(""maincontent"")' onresize='notifyDocumentHeightChanged(""maincontent"")'> | |
<div id='maincontent'>" + html + @"</div> | |
</body> | |
</html>"; | |
} | |
private async void RecWebTapped(object sender, TappedRoutedEventArgs e) | |
{ | |
var p = e.GetPosition(this.WebviewContent); | |
var x = Convert.ToInt32(p.X); | |
var y = Convert.ToInt32(p.Y); | |
string[] size = | |
{ | |
x.ToString(), | |
y.ToString() | |
}; | |
await this.WebviewContent.InvokeScriptAsync("loadLink", size); | |
} | |
private void WebviewContentScriptNotify(object sender, NotifyEventArgs e) | |
{ | |
if (e.Value.Contains("rendered_height")) | |
{ | |
var valuePair = e.Value.Split('='); | |
if (valuePair != null && valuePair[0] == "rendered_height") | |
{ | |
var renderedHeight = double.Parse(valuePair[1]) + 20; | |
this.WebviewContent.Height = renderedHeight; | |
} | |
} | |
} | |
#endregion | |
} | |
} |