Bạn không thể sử dụng một đơn FlowDocument
để tạo tài liệu lớn vì bạn sẽ hết bộ nhớ. Tuy nhiên, nếu có thể tạo đầu ra của bạn dưới dạng một chuỗi là FlowDocument
hoặc là cực kỳ cao ItemsControl
, điều đó là có thể.
tôi đã tìm thấy cách dễ nhất để làm điều này là để phân lớp DocumentPaginator
và vượt qua một thể hiện của lớp con tôi để XpsDocumentWriter.Write
:
var document = new XpsDocument(...);
var writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(new WidgetPaginator { Widget = widgetBeingPrinted, PageSize = ... });
Lớp WidgetPaginator
chính nó là khá đơn giản:
class WidgetPaginator : DocumentPaginator, IDocumentPaginatorSource
{
Size _pageSize;
public Widget Widget { get; set; }
public override Size PageSize { get { return _pageSize; } set { _pageSize = value; } }
public override bool IsPageCountValid { return true; }
public override IDocumentPaginatorSource Source { return this; }
public override DocumentPaginator DocumentPaginator { return this; }
public override int PageCount
{
get
{
return ...; // Compute page count
}
}
public override DocumentPage GetPaget(int pageNumber)
{
var visual = ...; // Compute page visual
Rect box = new Rect(0,0,_pageSize.With, _pageSize.Height);
return new DocumentPage(visual, _pageSize, box, box);
}
Tất nhiên bạn vẫn phải viết mã thực sự tạo ra các trang.
Nếu bạn muốn sử dụng một loạt các FlowDocuments để tạo ra tài liệu của bạn
Nếu bạn đang sử dụng một chuỗi các FlowDocuments
đẻ ra tài liệu một phần của bạn tại một thời điểm thay vì tất cả cùng một lúc, tùy chỉnh của bạn người điều hành có thể làm việc theo hai lần:
- Lần đầu tiên xảy ra khi người tạo trang được xây dựng. Nó tạo ra một
FlowDocument
cho mỗi phần, sau đó nhận được DocumentPaginator
để truy xuất số trang. Mỗi phần của FlowDocument
bị hủy sau khi các trang được tính.
- Lần truy cập thứ hai xảy ra trong quá trình xuất tài liệu thực tế: Nếu số được chuyển đến
GetPage()
là trong FlowDocument
được tạo gần đây nhất, GetPage()
chỉ cần gọi trình thu thập tài liệu đó để nhận trang thích hợp. Nếu không, nó sẽ loại bỏ FlowDocument đó và tạo ra một FlowDocument
cho phần mới, lấy người tạo trang của nó, sau đó gọi số GetPage()
trên trình tạo trang.
Chiến lược này cho phép bạn tiếp tục sử dụng FlowDocuments
như bạn đã từng, miễn là bạn có thể chia dữ liệu thành "phần" với từng tài liệu riêng. Trình tùy chỉnh của bạn sau đó xử lý hiệu quả tất cả các FlowDocuments riêng lẻ dưới dạng một tài liệu lớn. Điều này tương tự với tính năng "Tài liệu chính" của Word.
Nếu bạn có thể làm cho dữ liệu của bạn như một chuỗi các hình ảnh theo chiều dọc xếp chồng lên nhau
Trong trường hợp này, các kỹ thuật tương tự có thể được sử dụng.Trong lần vượt qua đầu tiên, tất cả hình ảnh được tạo theo thứ tự và được đo để xem số lượng hình ảnh sẽ phù hợp trên một trang. Cấu trúc dữ liệu được xây dựng để cho biết phạm vi của hình ảnh (theo chỉ mục hoặc bất kỳ thứ gì) được tìm thấy trên một trang nhất định. Trong quá trình này mỗi lần trang được lấp đầy, hình ảnh tiếp theo được đặt trên một trang mới. Đầu trang và chân trang sẽ được xử lý theo cách hiển nhiên.
Trong quá trình tạo tài liệu thực tế, phương pháp GetPage()
được triển khai để tạo lại hình ảnh đã được quyết định trước đó trên một trang nhất định và kết hợp chúng bằng DockPanel dọc hoặc bảng điều khiển khác do bạn chọn.
Tôi đã tìm thấy kỹ thuật này linh hoạt hơn về lâu dài vì bạn không phải giải quyết các giới hạn của FlowDocument
.
> The OutOfMemeoryExcpetion có nhiều khả năng gây ra bởi ... Nói cách khác, bạn chưa thực sự kiểm tra. Chúng tôi cần thêm thông tin để cho bạn biết vấn đề là gì. –
@bitbonk Tôi hiện đang gặp sự cố tương tự. Bạn đã bao giờ tìm thấy một giải pháp? –