c# windows-runtime microsoft-metro winrt-xaml .net-4.5

c# - ¿Cómo imprimo el contenido de WebView en una aplicación de la Tienda Windows?



windows-runtime microsoft-metro (2)

Aquí está la sintaxis básica de impresión.

PrintManager.PrintTaskRequested += printManager_PrintTaskRequested; void printManager_PrintTaskRequested( Windows.Graphics.Printing.PrintManager sender, Windows.Graphics.Printing.PrintTaskRequestedEventArgs args) { ... }

Tengo una aplicación de Metro y estoy intentando imprimir el contenido de un control de WebView . Usando la muestra de impresión de MSDN como mi fuente de referencia. Simplemente cambio el XAML en el área printableArea siguiente manera:

<RichTextBlock> <Paragraph> <InlineUIContainer> <WebView Width="800" Height="2000" Source="http://www.stackoverflow.com"/> </InlineUIContainer> </Paragraph> </RichTextBlock>

Esto funciona parcialmente. El problema es que el área Visible en las dimensiones especificadas se imprime, es decir, el área que se puede desplazar no se imprime y tampoco aparece como varias páginas en la vista preliminar de impresión .

Ya casi estoy allí, agradecería un poco de ayuda para que esto funcione como se esperaba.

No he encontrado ninguna muestra en ninguna parte, que aborda este problema específico.

Incluso he probado las soluciones aquí: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/5edcb239-7a5b-49f7-87e3-e5a253b809c4

No soy el primero que experimenta el mismo problema / similar: http://social.msdn.microsoft.com/Search/en-US/?Refinement=112&query=print%20webview#refinementChanges=180&pageNumber=1&showMore=false

Dispuesto a dar a cualquiera que pueda resolver este problema una recompensa de 100 puntos. Apreciaría un tutorial, código de ejemplo o proyecto simulado como una solución.


Claro aquí tienes.

Primero, puede cambiar el tamaño de la vista WebView al contenido real. Luego, escala el WebView nuevo al tamaño original. Requeriría una invocación de script y un ScaleTransform . Bastante simple, de verdad.

Me gusta esto:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <WebView x:Name="MyWebView" Source="http://www..com" /> </Grid> void MyWebView_LoadCompleted(object sender, NavigationEventArgs e) { var _Original = MyWebView.RenderSize; // ask the content its width var _WidthString = MyWebView.InvokeScript("eval", new[] { "document.body.scrollWidth.toString()" }); int _Width; if (!int.TryParse(_WidthString, out _Width)) throw new Exception(string.Format("failure/width:{0}", _WidthString)); // ask the content its height var _HeightString = MyWebView.InvokeScript("eval", new[] { "document.body.scrollHeight.toString()" }); int _Height; if (!int.TryParse(_HeightString, out _Height)) throw new Exception(string.Format("failure/height:{0}", _HeightString)); // resize the webview to the content MyWebView.Width = _Width; MyWebView.Height = _Height; // scale the webview back to original height (can''t do both height & width) var _Transform = (MyWebView.RenderTransform as ScaleTransform) ?? (MyWebView.RenderTransform = new ScaleTransform()) as ScaleTransform; var _Scale = _Original.Height / _Height; _Transform.ScaleX = _Transform.ScaleY = _Scale; }

Esto dará como resultado una vista web muy alta y estrecha como esta:

Pero eso no es lo que quieres.

Aunque puede cambiar el tamaño del rectángulo resultante para que no tenga una forma tan loca, el Contrato de impresión en Windows 8 requiere que lo proporcione con una sola página. No hace la paginación por ti. Como resultado, lo que realmente necesita es recuperar el sitio web individual, una página a la vez.

El primer enfoque es la base sobre cómo hacer eso. Pero es necesario que corrija el tamaño del rectángulo al tamaño de la página que le envió la tarea de impresión de Windows 8. Esto se basará en la selección de la impresora del usuario. Por ejemplo, Carta contra A4 (en Reino Unido). Luego, utilizando la propiedad Estirar del pincel, puede asegurarse de que se recorte. Luego, utilizando la propiedad Transformar del pincel, puede deslizarlo hacia arriba y hacia abajo dentro del rectángulo hasta que muestre la página que desea imprimir.

Así es cómo:

<Grid Background="Blue"> <Grid.ColumnDefinitions> <ColumnDefinition Width="995" /> <ColumnDefinition Width="300" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <WebView Grid.Column="0" x:Name="MyWebView" Source="http://www..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; }

Entonces, la interfaz de usuario será algo como esto, donde la columna de la izquierda es WebView, la segunda columna (centro) es el todo en uno como nuestra primera solución, y la tercera, un repetidor que muestra las páginas individuales listas para imprimir.

¡Por supuesto que la magia está realmente en el método GetWebPages ()! No me importa decirlo, es una maravilla simple, bastante fácil por la forma en que funcionan C # y Transforms.

Tenga en cuenta que esto no está completo . Sí, rompe la página por ti, pero no puedo estar seguro de cuánto margen quieres en tu página. Así que el ajuste requerido es pequeño, pero quería mencionarlo. Esto es el 98% del código que necesitará para dividir una vista web y prepararla para la tarea de impresión de Windows 8 en respuesta al evento de paginación. Luego, pásale los rectángulos uno por uno.

Dicho esto, esta es probablemente la solución más completa a este problema en Internet. :)

¡¡La mejor de las suertes!!