更新3
现在这个问题有赏金了。示例项目和问题简介位于页面底部的TL;DR;下方,所以节省一些阅读时间并跳到结尾吧!
...
我一直在尝试使用NavigateToString通过静态加载页面来运行JerryNixon的这个高度详细、得票最多的答案。我不明白为什么这不应该起作用,但必须承认代码中有些部分让我感到困惑。原始答案在此处,但为了完整起见,我将在此复制代码。Jerry为那些想要从
WebView
打印的人提供了以下示例/解决方案。<Grid Background="Blue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="995" />
<ColumnDefinition Width="300" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<WebView Grid.Column="0" x:Name="MyWebView" Source="http://www.stackoverflow.com" HorizontalAlignment="Right" />
<Rectangle Grid.Column="1" x:Name="MyWebViewRectangle" Fill="Red" />
<ScrollViewer Grid.Column="2" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="MyPrintPages" VerticalAlignment="Top" HorizontalAlignment="Left">
<Rectangle Height="150" Width="100" Fill="White" Margin="5" />
<Rectangle Height="150" Width="100" Fill="White" Margin="5" />
<Rectangle Height="150" Width="100" Fill="White" Margin="5" />
<Rectangle Height="150" Width="100" Fill="White" Margin="5" />
<Rectangle Height="150" Width="100" Fill="White" Margin="5" />
</ItemsControl>
</ScrollViewer>
</Grid>
public MainPage()
{
this.InitializeComponent();
MyWebView.LoadCompleted += MyWebView_LoadCompleted;
}
void MyWebView_LoadCompleted(object sender, NavigationEventArgs e)
{
MyWebViewRectangle.Fill = GetWebViewBrush(MyWebView);
MyPrintPages.ItemsSource = GetWebPages(MyWebView, new Windows.Foundation.Size(100d, 150d));
MyWebView.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
WebViewBrush GetWebViewBrush(WebView webView)
{
// resize width to content
var _OriginalWidth = webView.Width;
var _WidthString = webView.InvokeScript("eval",
new[] { "document.body.scrollWidth.toString()" });
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:{0}", _WidthString));
webView.Width = _ContentWidth;
// resize height to content
var _OriginalHeight = webView.Height;
var _HeightString = webView.InvokeScript("eval",
new[] { "document.body.scrollHeight.toString()" });
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:{0}", _HeightString));
webView.Height = _ContentHeight;
// create brush
var _OriginalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
var _Brush = new WebViewBrush
{
SourceName = webView.Name,
Stretch = Stretch.Uniform
};
_Brush.Redraw();
// reset, return
webView.Width = _OriginalWidth;
webView.Height = _OriginalHeight;
webView.Visibility = _OriginalVisibilty;
return _Brush;
}
IEnumerable<FrameworkElement> GetWebPages(WebView webView, Windows.Foundation.Size page)
{
// ask the content its width
var _WidthString = webView.InvokeScript("eval",
new[] { "document.body.scrollWidth.toString()" });
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:{0}", _WidthString));
webView.Width = _ContentWidth;
// ask the content its height
var _HeightString = webView.InvokeScript("eval",
new[] { "document.body.scrollHeight.toString()" });
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:{0}", _HeightString));
webView.Height = _ContentHeight;
// how many pages will there be?
var _Scale = page.Width / _ContentWidth;
var _ScaledHeight = (_ContentHeight * _Scale);
var _PageCount = (double)_ScaledHeight / page.Height;
_PageCount = _PageCount + ((_PageCount > (int)_PageCount) ? 1 : 0);
// create the pages
var _Pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)_PageCount; i++)
{
var _TranslateY = -page.Height * i;
var _Page = new Windows.UI.Xaml.Shapes.Rectangle
{
Height = page.Height,
Width = page.Width,
Margin = new Thickness(5),
Tag = new TranslateTransform { Y = _TranslateY },
};
_Page.Loaded += (s, e) =>
{
var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var _Brush = GetWebViewBrush(webView);
_Brush.Stretch = Stretch.UniformToFill;
_Brush.AlignmentY = AlignmentY.Top;
_Brush.Transform = _Rectangle.Tag as TranslateTransform;
_Rectangle.Fill = _Brush;
};
_Pages.Add(_Page);
}
return _Pages;
}
我的唯一更改是从 WebView 中移除“Source”属性,并将此行添加到“MainPage()”方法中。
var html = await Windows.Storage.PathIO.ReadTextAsync("ms-appx:///Assets/sherlock.html");
MyWebView.NavigateToString(html);
是阿瑟·柯南·道尔(Arthur Conan Doyle)小说《红发联盟》的一部分,这个HTML页面的完整代码在这里 - 注意末尾附近的一段重复出现了几次。这是为了测试而做的,我会在下面解释。
这个样本最初对我来说有效,对于一个小文件。(Sherlock.html没有填充章节)
然而,当我处理大于某个文件大小(通常在4000字以上)的文件时,会出现以下行为。
WebView缩小到非常窄的视图
(请参见更新说明,了解为什么将其划掉)
然后屏幕变灰。(我感觉有点傻把一个灰色屏幕的截图发布出来,但我在这里试图尽可能详细)
网格
被简单地移除了。我尝试调整代码的每个部分,但似乎无法确定问题的原因。此外,该代码的某些部分让我困惑不解。例如,在Load_Completed
方法中。
MyWebViewRectangle.Fill = GetWebViewBrush(MyWebView);
MyPrintPages.ItemsSource = GetWebPages(MyWebView, new Windows.Foundation.Size(100d, 150d));
MyWebView.Visibility = Windows.UI.Xaml.Visibility.Visible;
Line1:
MyWebViewRectangle
被WebView
的截图填充。为什么?这个控件再也没有被引用过。我猜可能是为了使用户更清晰地查看页面,但似乎没有程序目的。Line3:
MyWebView.Visibility
被设置为Visible
。这在GetWebViewBrush
中再次发生。var _OriginalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
// and a few lines later...
webView.Visibility = _OriginalVisibilty;
据我所知,Webview从未被“Collapsed”,但它被设置为“Visible”三次。
如果有人能向我解释其中任何一点(甚至是JerryNixon自己?)我会非常感激。我已经花了几个月的时间来开发应用程序,这是最后一个难题。我不能没有打印功能就发布!
更新
今天早上做了一些发现。我之前一直在XAML中设置WebView的宽度,但即使是最小的文件也会失败。基于这个发现,我在html文件中将宽度设置为800像素,然后它就可以工作了。太好了,问题解决了,对吗?不幸的是,不是这样的。我再次尝试使用更长的文件(《红发联盟》的完整版本,here),同样的问题再次发生了。现在情况变得越来越奇怪了。
我在GetWebPages方法中的webView.Height = _ContentHeight;处插入了一个断点。这向我展示了_ContentHeight确切地是“13241”。
然而,插入断点可使代码正常工作。一旦我点击中断并继续,它似乎全部加载完毕。虽然奇怪的是,直到我将鼠标悬停在滚动条上之前,WebView才会变得不可见。
如果我删除断点,我会再次看到灰色屏幕。
如果我手动将_ContentHeight
设置为13230,页面就会加载。这似乎是一个神奇的数字。任何比这更高的数字都会导致页面失败。但是,如果我将html的宽度改为小于800px,它也会失败。因此,逻辑上讲,存在一种800:13230像素(或1:16.5375)的神奇比例。如果我超过这个比例,我就会触发灰色死屏。我可以禁用红色矩形并将GetWebPages
限制为3页,灰色屏幕仍然存在。这告诉我问题出在WebView
本身。
如果我设置一个断点,这个问题就消失了。
还要注意,在它正常工作时MyWebViewRectangle
中的额外空格和MyPrintPages
中的额外空白页面:
LongRunningScriptDetected
、UnsafeContentWarningDisplaying
和UnviewableContentIdentified
这是我的示例项目的完整源代码:
https://onedrive.live.com/redir?resid=EE99EF9560A6740E!110509&authkey=!ACrZgm6uq5k5yck&ithint=file%2czip
更新2有些进展。
我在示例文件中放置了一些标头(通过试错找到每个计算页面的“底部”),并增加了页面大小,以便能够看到标记。虽然有9个页面,但只有5个和一小部分第6页被呈现。
GetWebPages
创建了9个页面对象,但只有5个左右具有呈现的HTML内容。其余为空。
我已经检查了代码并进行了一些修改,现在我根本不再遇到灰屏问题。然而,每3次中大约有2次只渲染第一页,并且它被裁剪了。这似乎是完全随机的。当渲染9页时,并非所有页面都有内容,正如所述。
以下是我的更改:
添加新方法
Resize_WebView()
public void ResizeWebView()
{
OriginalHeight = MyWebView.Height;
var _WidthString = MyWebView.InvokeScript("eval", new[] { "document.body.scrollWidth.toString()" });
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:{0}", _WidthString));
MyWebView.Width = _ContentWidth;
// ask the content its height
var _HeightString = MyWebView.InvokeScript("eval", new[] { "document.body.scrollHeight.toString()" });
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:{0}", _HeightString));
MyWebView.Height = _ContentHeight;
}
在
MyWebView_LoadCompleted
中注释掉了矩形填充,并添加了调用ResizeWebView()的语句:void MyWebView_LoadCompleted(object sender, NavigationEventArgs e)
{
ResizeWebView();
//MyWebViewRectangle.Fill = GetWebViewBrush(MyWebView);
MyPrintPages.ItemsSource = GetWebPages(MyWebView, new Windows.Foundation.Size(300d, 450d));
}
在
GetMyWebPages
中更改了刷子加载的位置:IEnumerable<FrameworkElement> GetWebPages(WebView webView, Windows.Foundation.Size page)
{
// ask the content its width
/*var _WidthString = webView.InvokeScript("eval",
new[] { "document.body.scrollWidth.toString()" });
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:{0}", _WidthString));
webView.Width = _ContentWidth;
// ask the content its height
var _HeightString = webView.InvokeScript("eval",
new[] { "document.body.scrollHeight.toString()" });
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:{0}", _HeightString));
webView.Height = _ContentHeight;
// Manually set _ContentHeight: comment out the above block and uncomment this to test.
// int _ContentHeight = 13230;
// webView.Height = _ContentHeight;*/
// how many pages will there be?
//var _Scale = page.Width / _ContentWidth;
var _Scale = page.Width / webView.Width; // now sourced directly from webview
//var _ScaledHeight = (_ContentHeight * _Scale);
var _ScaledHeight = (webView.Height * _Scale); // now sourced directly from webview
var _PageCount = (double)_ScaledHeight / page.Height;
_PageCount = _PageCount + ((_PageCount > (int)_PageCount) ? 1 : 0);
// create the pages
var _Pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)_PageCount; i++)
{
var _TranslateY = -page.Height * i;
var _Page = new Windows.UI.Xaml.Shapes.Rectangle
{
Height = page.Height,
Width = page.Width,
Margin = new Thickness(5),
Tag = new TranslateTransform { Y = _TranslateY },
};
var _Brush = GetWebViewBrush(webView);
_Brush.Stretch = Stretch.UniformToFill;
_Brush.AlignmentY = AlignmentY.Top;
_Brush.Transform = _Page.Tag as TranslateTransform;
_Page.Fill = _Brush;
/*_Page.Loaded += async (s, e) =>
{
var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var _Brush = await GetMyWebViewBrush(webView);
_Brush.Stretch = Stretch.UniformToFill;
_Brush.AlignmentY = AlignmentY.Top;
_Brush.Transform = _Rectangle.Tag as TranslateTransform;
_Rectangle.Fill = _Brush;
};*/
_Pages.Add(_Page);
}
return _Pages;
}
从GetWebView
中移除了现在不必要的调整大小代码。
WebViewBrush GetWebViewBrush(WebView webView)
{
/*// resize width to content
var _OriginalWidth = webView.Width;
var _WidthString = webView.InvokeScript("eval",
new[] { "document.body.scrollWidth.toString()" });
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:{0}", _WidthString));
webView.Width = _ContentWidth;
// resize height to content
var _OriginalHeight = webView.Height;
var _HeightString = webView.InvokeScript("eval",
new[] { "document.body.scrollHeight.toString()" });
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:{0}", _HeightString));
webView.Height = _ContentHeight;
// create brush
var _OriginalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;*/
var _Brush = new WebViewBrush
{
SourceName = webView.Name,
Stretch = Stretch.Uniform
};
_Brush.Redraw();
// reset, return
/*webView.Width = _OriginalWidth;
webView.Height = _OriginalHeight;
webView.Visibility = _OriginalVisibilty;*/
return _Brush;
}
这是一个非常重要的问题。
简短概述:
加载并观察。文档中有9页。
- GetWebPages偶尔只加载一页,被裁剪了
- 其余时间,GetWebPages加载页面1-5、部分6和3个空白页面
这几乎是你需要知道的所有内容来回答这个问题。
我在这个问题上设置了赏金。我正在寻找解决这个问题的方法,并且如果可能的话,为每个页面添加填充以使文本不会溢出到边缘。
throw new Exception...
。没有异常。再次,只有一个灰色屏幕。我验证了这不是网格被移除的问题 - 页面本身的背景颜色是较深的灰色。这个灰色是“应用程序启动”灰色。 - roryok