/// <summary>
        /// Build cache
        /// </summary>
        private void BuildCache()
        {
            DocumentWalker walker = new DocumentWalker();

            walker.VisualVisited += WalkerVisualVisited;
            walker.Walk(_flowDocument);
        }
예제 #2
0
        /// <summary>
        /// Clones a visual block
        /// </summary>
        /// <param name="block">block to be cloned</param>
        /// <param name="pageNumber">current page number</param>
        /// <returns>cloned block</returns>
        /// <exception cref="InvalidProgramException">Error cloning XAML block</exception>
        private ContainerVisual CloneVisualBlock(Block block, int pageNumber)
        {
            FlowDocument tmpDoc = new FlowDocument();

            tmpDoc.ColumnWidth = double.PositiveInfinity;
            tmpDoc.PageHeight  = _report.PageHeight;
            tmpDoc.PageWidth   = _report.PageWidth;
            tmpDoc.PagePadding = new Thickness(0);

            string xaml     = XamlWriter.Save(block);
            Block  newBlock = XamlReader.Parse(xaml) as Block;

            if (newBlock == null)
            {
                throw new InvalidProgramException("Error cloning XAML block");
            }
            tmpDoc.Blocks.Add(newBlock);

            DocumentWalker walkerBlock = new DocumentWalker();
            ArrayList      blockValues = new ArrayList();

            blockValues.AddRange(walkerBlock.Walk <IInlineContextValue>(tmpDoc));

            // fill context values
            FillContextValues(blockValues, pageNumber);

            DocumentPage dp = ((IDocumentPaginatorSource)tmpDoc).DocumentPaginator.GetPage(0);

            return((ContainerVisual)dp.Visual);
        }
예제 #3
0
        /// <summary>
        /// Creates a flow document of the report data
        /// </summary>
        /// <returns></returns>
        /// <exception cref="ArgumentException">XAML data does not represent a FlowDocument</exception>
        /// <exception cref="ArgumentException">Flow document must have a specified page height</exception>
        /// <exception cref="ArgumentException">Flow document must have a specified page width</exception>
        /// <exception cref="ArgumentException">"Flow document must have only one ReportProperties section, but it has {0}"</exception>
        internal FlowDocument CreateFlowDocument()
        {
            MemoryStream mem = new MemoryStream();

            byte[] buf = Encoding.UTF8.GetBytes(_xamlData);
            mem.Write(buf, 0, buf.Length);
            mem.Position = 0;
            FlowDocument res = XamlReader.Load(mem) as FlowDocument;

            if (res == null)
            {
                throw new ArgumentException("XAML data does not represent a FlowDocument");
            }

            if (res.PageHeight == double.NaN)
            {
                throw new ArgumentException("Flow document must have a specified page height");
            }
            if (res.PageWidth == double.NaN)
            {
                throw new ArgumentException("Flow document must have a specified page width");
            }

            // remember original values
            _pageHeight = res.PageHeight;
            _pageWidth  = res.PageWidth;

            // search report properties
            DocumentWalker             walker     = new DocumentWalker();
            List <SectionReportHeader> headers    = walker.Walk <SectionReportHeader>(res);
            List <SectionReportFooter> footers    = walker.Walk <SectionReportFooter>(res);
            List <ReportProperties>    properties = walker.Walk <ReportProperties>(res);

            if (properties.Count > 0)
            {
                if (properties.Count > 1)
                {
                    throw new ArgumentException(String.Format("Flow document must have only one ReportProperties section, but it has {0}", properties.Count));
                }
                ReportProperties prop = properties[0];
                if (prop.ReportName != null)
                {
                    ReportName = prop.ReportName;
                }
                if (prop.ReportTitle != null)
                {
                    ReportTitle = prop.ReportTitle;
                }

                // remove properties section from FlowDocument
                DependencyObject parent = prop.Parent;
                if (parent is FlowDocument)
                {
                    ((FlowDocument)parent).Blocks.Remove(prop); parent = null;
                }
                if (parent is Section)
                {
                    ((Section)parent).Blocks.Remove(prop);
                }
            }

            if (headers.Count > 0)
            {
                PageHeaderHeight = headers[0].PageHeaderHeight;
            }
            if (footers.Count > 0)
            {
                PageFooterHeight = footers[0].PageFooterHeight;
            }

            // make height smaller to have enough space for page header and page footer
            res.PageHeight = _pageHeight - _pageHeight * (PageHeaderHeight + PageFooterHeight) / 100d;

            // search image objects
            List <Image> images = new List <Image>();

            walker.Tag            = images;
            walker.VisualVisited += WalkerVisualVisited;
            walker.Walk(res);

            // load all images
            foreach (Image image in images)
            {
                if (ImageProcessing != null)
                {
                    ImageProcessing(this, new ImageEventArgs(this, image));
                }
                try
                {
                    if (image.Tag is string)
                    {
                        image.Source = new BitmapImage(new Uri("file:///" + Path.Combine(_xamlImagePath, image.Tag.ToString())));
                    }
                }
                catch (Exception ex)
                {
                    // fire event on exception and check for Handled = true after each invoke
                    if (ImageError != null)
                    {
                        bool handled = false;
                        lock (ImageError)
                        {
                            ImageErrorEventArgs eventArgs = new ImageErrorEventArgs(ex, this, image);
                            foreach (var ed in ImageError.GetInvocationList())
                            {
                                ed.DynamicInvoke(this, eventArgs);
                                if (eventArgs.Handled)
                                {
                                    handled = true; break;
                                }
                            }
                        }
                        if (!handled)
                        {
                            throw;
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
                if (ImageProcessed != null)
                {
                    ImageProcessed(this, new ImageEventArgs(this, image));
                }
                // TODO: find a better way to specify file names
            }

            return(res);
        }