WPF - 自动行号的FlowDocument? [英] WPF - Auto Line Number for FlowDocument?

查看:225
本文介绍了WPF - 自动行号的FlowDocument?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始在合同生成程序为我的当前项目,并要求之一是,每个合同的线条必须编号。数应设在与垂直分离规则从文档内容的其余部分的编号左旁。

I'm just starting on a contract generation routine for my current project and one of the requirements is that each of the lines in the contract must be numbered. The number should be located in the left margin with a vertical rule separating the numbering from the rest of the document content.

我敢肯定,我可以解决这一要求一个固定文档,但它不会很有趣。反正我有可以用的FlowDocument,而不是这样做呢?

I'm pretty sure I can tackle this requirement with a FixedDocument, but it won't be fun. Is there anyway I can do this with a FlowDocument instead?

推荐答案

您可以用固定文档与我WpfPrint帮助做到这一点很容易类,贴在下面。要使用它的XPS创造仅仅使用了XPS的构造器:

You can do this with a FixedDocument quite easily with my WpfPrint helper class, posted below. To use it for XPS creation just use the constructor for XPS:

WpfPrint printer = new WpfPrint(new Size(1024, 768));
printer.CurrentElementMargin = new Thickness(2, 2, 2, 2);
printer.CurrentFontFamily = new FontFamily("Arial");
printer.CurrentFontSize = BaseFontSize;
printer.MarginX = 24;
printer.MarginY = 24;

您现在可以通过循环,并添加任何你想要的;的TextBlocks将最有可能是你要找的:

You can now loop through and add whatever you want; TextBlocks would most likely be what you were looking for:

printer.AddTextBlock("Basics", printer.PageSizeUsed.Width, 0, WpfPrint.ElementFlags.NewLine | WpfPrint.ElementFlags.BottomCheck2);

如果你创建它们包裹他们会包装自己;每个项目,因为它被添加,进行测量。如果它不适合页面,辅助类增加了新的一页,它流到新的页面,让你得到你的FlowDocument想要的东西。您可以随时更改CurX和CURY放置物品时跳过水平或垂直空间。当你做,你可以打印到这样的打印机:

They'll wrap themselves if you create them wrapped; each item, as it is added, is measured. If it doesn't fit on the page, the helper class adds a new page and flows it onto the new page, so you get what you wanted from FlowDocument. You can change CurX and CurY at any time to skip horizontal or vertical space when placing items. When you are done, you can print to a printer like this:

// Print final document
XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(dlg.PrintQueue);
xpsDocumentWriter.Write(printer.CurrentFixedDocument);



或者你也可以保存为XPS文件:

Or you can save as an XPS file:

using (XpsDocument doc = new XpsDocument(filename, FileAccess.Write))
{
    XpsDocumentWriter xpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(doc);
    xpsDocumentWriter.Write(printer.CurrentFixedDocument);
}

下面是辅助类。请享用!你永远也不会想再次使用的FlowDocument: - )

Here is the helper class. Enjoy! You'll never want to use a FlowDocument again :-)

//****************************************************************************************
// WpfPrint
//
// Various helpers for printing WPF UI to a printer
//****************************************************************************************

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Controls;
using System.Windows.Xps;
using System.Windows;
using System.Printing;
using System.Windows.Media;


namespace csheet
{
    /// <summary>
    /// Various helpers for printing WPF UI to a printer
    /// </summary>
    public class WpfPrint
    {
        #region Supporting Types
        //****************************************************************************************
        // Suporting Types
        //****************************************************************************************

        /// <summary>
        /// Element flags define the way the elements print; OR them for multiple effects
        /// </summary>
        [Flags]
        public enum ElementFlags
        {
            /// <summary>No special flags</summary>
            None = 0,

            /// <summary>Move to the next line after output</summary>
            NewLine = 1,

            /// <summary>if there isn't 2x room, then do new page first</summary>
            BottomCheck2 = 2,

            /// <summary>Center the item horizontally</summary>
            HorzCenter = 4,

            /// <summary>Right align the item (center overrides)</summary>
            HorzRight = 8
        }

        #endregion Supporting Types

        #region Data
        //****************************************************************************************
        // Data
        //****************************************************************************************

        FixedDocument _fixedDocument;
        FixedPage _curFixedPage;
        Canvas _curCanvas;
        double _marginX;
        double _marginY;
        Size _infiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);

        #endregion Data

        #region Properties
        //****************************************************************************************
        // Properties
        //****************************************************************************************

        /// <summary>Current font family used for known objects</summary>
        public FontFamily CurrentFontFamily { get; set; }


        /// <summary>Current font size used for known objects</summary>
        public double CurrentFontSize { get; set; }


        /// <summary>Current font weight used for known objects</summary>
        public FontWeight CurrentFontWeight { get; set; }


        /// <summary>Current font style used for known objects</summary>
        public FontStyle CurrentFontStyle { get; set; }


        /// <summary>Current margin for known objects</summary>
        public Thickness CurrentElementMargin { get; set; }


        /// <summary>Current background for known objects</summary>
        public Brush CurrentElementBackground { get; set; }


        /// <summary>Current foreground for known objects</summary>
        public Brush CurrentElementForeground { get; set; }


        /// <summary>Gets the current fixed document being worked on</summary>
        public FixedDocument CurrentFixedDocument
        {
            get { return _fixedDocument; }
        }


        /// <summary>The current horizontal position</summary>
        public double CurX { get; set; }


        /// <summary>The current vertical position</summary>
        public double CurY { get; set; }


        /// <summary>The starting and ending X margins on the page</summary>
        public double MarginX
        {
            get { return _marginX; }
            set
            {
                if (value < 0)
                    value = 0;
                _marginX = value;
                if (CurX < _marginX)
                    CurX = _marginX;
            }
        }


        /// <summary>The starting and ending Y margins on the page</summary>
        public double MarginY
        {
            get { return _marginY; }
            set
            {
                if (value < 0)
                    value = 0;
                _marginY = value;
                if (CurY < _marginY)
                    CurY = _marginY;
            }
        }


        /// <summary>Gets the page size for the document minus the margins</summary>
        public Size PageSizeUsed
        {
            get
            {
                Size sz = CurrentFixedDocument.DocumentPaginator.PageSize;
                sz.Width -= 2 * _marginX;
                sz.Height -= 2 * _marginY;
                return sz;
            }
        }

        #endregion Properties

        #region Construction
        //****************************************************************************************
        // Construction
        //****************************************************************************************

        /// <summary>
        /// Constructor for printing
        /// </summary>
        /// <param name="printQueue"></param>
        /// <param name="printTicket"></param>
        public WpfPrint(PrintQueue printQueue, PrintTicket printTicket)
        {
            PrintCapabilities capabilities = printQueue.GetPrintCapabilities(printTicket);

            Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
            _fixedDocument = new FixedDocument();
            _fixedDocument.DocumentPaginator.PageSize = sz;

            StartPage();
        }


        /// <summary>
        /// Constructor for XPS creation
        /// </summary>
        /// <param name="sz"></param>
        public WpfPrint(Size sz)
        {
            _fixedDocument = new FixedDocument();
            _fixedDocument.DocumentPaginator.PageSize = sz;

            StartPage();
        }

        #endregion Construction

        #region Interfaces
        //****************************************************************************************
        // Interfaces
        //****************************************************************************************

        /// <summary>
        /// Add a new page to the document (start a new page)
        /// </summary>
        public void StartPage()
        {
            // Create a new page content and fixed page
            PageContent content = new PageContent();
            _fixedDocument.Pages.Add(content);
            _curFixedPage = new FixedPage();
            ((IAddChild)content).AddChild(_curFixedPage);

            // Create a new drawing canvas for the page
            _curCanvas = new Canvas();
            _curCanvas.Width = _fixedDocument.DocumentPaginator.PageSize.Width;
            _curCanvas.Height = _fixedDocument.DocumentPaginator.PageSize.Height;
            _curFixedPage.Children.Add(_curCanvas);

            // Reset the current position
            CurX = MarginX;
            CurY = MarginY;
        }


        /// <summary>
        /// Adds a new element at the current position, and updates the current position
        /// </summary>
        /// <param name="element">New element to add</param>
        /// <param name="flags">Print options</param>
        public void AddUIElement(UIElement element, ElementFlags flags)
        {
            element.Measure(_infiniteSize);
            if (CurX > _fixedDocument.DocumentPaginator.PageSize.Width - MarginX)
            {
                CurY += element.DesiredSize.Height;
                CurX = MarginX;
            }
            double extraCheck = 0;
            if ((flags & ElementFlags.BottomCheck2) == ElementFlags.BottomCheck2)
                extraCheck = element.DesiredSize.Height;
            if (CurY > _fixedDocument.DocumentPaginator.PageSize.Height - MarginY - extraCheck)
                StartPage();

            _curCanvas.Children.Add(element);
            element.SetValue(Canvas.LeftProperty, CurX);
            element.SetValue(Canvas.TopProperty, CurY);

            CurX += element.DesiredSize.Width;
            if ((flags & ElementFlags.NewLine) == ElementFlags.NewLine)
            {
                CurX = MarginX;
                CurY += element.DesiredSize.Height;
            }
        }


        /// <summary>
        /// Add a current style TextBlock element at the current position
        /// </summary>
        /// <param name="text">Text to add</param>
        /// <param name="width">Width of element</param>
        /// <param name="height">Height of element</param>
        /// <param name="flags">Print options</param>
        public void AddTextBlock(string text, double width, double height, ElementFlags flags)
        {
            TextBlock tb = new TextBlock();
            tb.Text = text;
            tb.FontFamily = CurrentFontFamily;
            tb.FontSize = CurrentFontSize;
            tb.FontWeight = CurrentFontWeight;
            tb.FontStyle = CurrentFontStyle;
            tb.VerticalAlignment = VerticalAlignment.Center;
            if ((flags & ElementFlags.HorzCenter) == ElementFlags.HorzCenter)
                tb.HorizontalAlignment = HorizontalAlignment.Center;
            else if ((flags & ElementFlags.HorzRight) == ElementFlags.HorzRight)
                tb.HorizontalAlignment = HorizontalAlignment.Right;
            tb.Margin = CurrentElementMargin;
            if (CurrentElementForeground != null)
                tb.Foreground = CurrentElementForeground;
            if (CurrentElementBackground != null)
                tb.Background = CurrentElementBackground;

            Grid grid = new Grid();
            if (CurrentElementBackground != null)
                grid.Background = CurrentElementBackground;
            if (width != 0)
                grid.Width = width;
            if (height != 0)
                grid.Height = height;
            grid.Children.Add(tb);

            AddUIElement(grid, flags);
        }


        /// <summary>
        /// Adds a current style TextBox element at the current position
        /// </summary>
        /// <param name="text">Text to add</param>
        /// <param name="width">Width of element</param>
        /// <param name="height">Height of element</param>
        /// <param name="flags">Print options</param>
        public void AddTextBox(string text, double width, double height, ElementFlags flags)
        {
            TextBox tb = new TextBox();
            tb.Text = text;
            tb.FontFamily = CurrentFontFamily;
            tb.FontSize = CurrentFontSize;
            tb.FontWeight = CurrentFontWeight;
            tb.FontStyle = CurrentFontStyle;
            tb.VerticalAlignment = VerticalAlignment.Center;
            tb.VerticalContentAlignment = VerticalAlignment.Center;
            if ((flags & ElementFlags.HorzCenter) == ElementFlags.HorzCenter)
                tb.HorizontalContentAlignment = HorizontalAlignment.Center;
            else if ((flags & ElementFlags.HorzRight) == ElementFlags.HorzRight)
                tb.HorizontalContentAlignment = HorizontalAlignment.Right;
            tb.Margin = CurrentElementMargin;
            if (CurrentElementBackground != null)
                tb.Background = CurrentElementBackground;
            if (CurrentElementForeground != null)
                tb.Foreground = CurrentElementForeground;

            Grid grid = new Grid();
            if (CurrentElementBackground != null)
                grid.Background = CurrentElementBackground;
            if (width != 0)
                grid.Width = width;
            if (height != 0)
                grid.Height = height;
            grid.Children.Add(tb);

            AddUIElement(grid, flags);
        }


        /// <summary>
        /// Add a current style CheckBox element at the current position
        /// </summary>
        /// <param name="value">Checkbox value to add</param>
        /// <param name="width">Width of element</param>
        /// <param name="height">Height of element</param>
        /// <param name="flags">Print options</param>
        public void AddCheckBox(bool value, double width, double height, ElementFlags flags)
        {
            CheckBox cb = new CheckBox();
            cb.IsChecked = value;
            cb.VerticalAlignment = VerticalAlignment.Center;
            if ((flags & ElementFlags.HorzCenter) == ElementFlags.HorzCenter)
                cb.HorizontalAlignment = HorizontalAlignment.Center;
            else if ((flags & ElementFlags.HorzRight) == ElementFlags.HorzRight)
                cb.HorizontalAlignment = HorizontalAlignment.Right;
            if (CurrentElementForeground != null)
                cb.Foreground = CurrentElementForeground;
            if (CurrentElementBackground != null)
                cb.Background = CurrentElementBackground;

            Grid grid = new Grid();
            if (CurrentElementBackground != null)
                grid.Background = CurrentElementBackground;
            if (width != 0)
                grid.Width = width;
            if (height != 0)
                grid.Height = height;
            grid.Children.Add(cb);

            AddUIElement(grid, flags);
        }

        #endregion Interfaces
    }
}

这篇关于WPF - 自动行号的FlowDocument?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆