OfficeViewer.Avalonia 0.1.6

dotnet add package OfficeViewer.Avalonia --version 0.1.6
                    
NuGet\Install-Package OfficeViewer.Avalonia -Version 0.1.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OfficeViewer.Avalonia" Version="0.1.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OfficeViewer.Avalonia" Version="0.1.6" />
                    
Directory.Packages.props
<PackageReference Include="OfficeViewer.Avalonia" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OfficeViewer.Avalonia --version 0.1.6
                    
#r "nuget: OfficeViewer.Avalonia, 0.1.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OfficeViewer.Avalonia@0.1.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OfficeViewer.Avalonia&version=0.1.6
                    
Install as a Cake Addin
#tool nuget:?package=OfficeViewer.Avalonia&version=0.1.6
                    
Install as a Cake Tool

OfficeViewer.Avalonia

中文 | English

中文说明

OfficeViewer.Avalonia 是用于 Avalonia 的只读 Office/PDF 原生预览控件包,提供 DOCX、PPTX、XLSX 与常见 PDF 的连续流式预览。

控件外层保持透明,不会强制宿主窗口背景。请由应用在外层使用 Border、Panel 或主题容器决定背景、圆角与阴影。

参考项目

DOCX、PPTX、XLSX 的文件读取、关系解析、样式模型和连续布局设计参考了 vue-office-core 项目。本包将对应思路移植为 C# 的 Open XML 解析和 Avalonia 控件渲染;它不包含 Vue、JavaScript 或 WebView 运行时,也不是对 Vue 组件的直接包装。

PDF 预览是当前项目独立实现的纯托管常见子集解析器:它不捆绑 PDF.js、PDFium 或 PdfPig。支持范围请见“格式范围与限制”。

包含控件

文档格式 命名空间和控件 读取结果属性
Word / DOCX OfficeViewer.Avalonia.Docx.DocxViewer PageCount
PowerPoint / PPTX OfficeViewer.Avalonia.Pptx.PptxViewer PageCount
Excel / XLSX OfficeViewer.Avalonia.Xlsx.XlsxViewer SheetCount、SelectedSheetIndex
PDF OfficeViewer.Avalonia.Pdf.PdfViewer PageCount

每个控件均提供可绑定的 byte[]? Document 属性。给 Document 赋新的文件字节数组会自动开始读取;将其清除或设为 null 会自动取消旧读取任务,并释放当前文档的模型、图像与可视资源。PPTX/PDF 仅会实例化可视页及少量相邻页,避免长文档持续占用图片内存。控件仍保留 LoadAsync 作为非绑定场景的便捷方法。

缩放

所有四个预览控件均支持 Ctrl + 鼠标滚轮缩放,以及触屏单指上下左右拖动、双指缩放。 内容超出视口时可以横向或纵向移动;双指缩放结束后,剩余一指可继续拖动。

安装

从你的 NuGet 源安装:

<PackageReference Include="OfficeViewer.Avalonia" Version="0.1.6" />

本仓库本地构建后的包目录如下,可在 Visual Studio、Rider 或 NuGet.Config 中添加为本地源:

OfficeViewer.Avalonia.NuGet\artifacts\packages

Avalonia XAML 用法

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:docx="clr-namespace:OfficeViewer.Avalonia.Docx;assembly=OfficeViewer.Avalonia"
        xmlns:pptx="clr-namespace:OfficeViewer.Avalonia.Pptx;assembly=OfficeViewer.Avalonia"
        xmlns:xlsx="clr-namespace:OfficeViewer.Avalonia.Xlsx;assembly=OfficeViewer.Avalonia"
        xmlns:pdf="clr-namespace:OfficeViewer.Avalonia.Pdf;assembly=OfficeViewer.Avalonia">
  <Grid RowDefinitions="Auto,*">
    <TextBlock Text="{Binding PageCount, ElementName=DocxPreview}" />
    <Border Grid.Row="1" Background="White" Padding="8">
      <docx:DocxViewer x:Name="DocxPreview"
                       Document="{Binding DocxDocument}" />
    </Border>
  </Grid>
</Window>

其他三种控件的声明方式:

<pptx:PptxViewer x:Name="PptxPreview"
                 Document="{Binding PptxDocument}" />
<pdf:PdfViewer x:Name="PdfPreview"
               Document="{Binding PdfDocument}" />
<xlsx:XlsxViewer x:Name="XlsxPreview"
                 Document="{Binding XlsxDocument}"
                 SelectedSheetIndex="{Binding SelectedWorksheet, Mode=TwoWay}" />

SelectedSheetIndex 从 0 开始。XLSX 控件故意不内置工作表选择器,请绑定到你自己的按钮、ComboBox、选项卡或 ViewModel。工作簿读取完成后,SheetCount 会更新。

C# 加载与释放

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public sealed class OfficePreviewViewModel : INotifyPropertyChanged
{
    private byte[]? _docxDocument;
    private byte[]? _pptxDocument;
    private byte[]? _xlsxDocument;
    private byte[]? _pdfDocument;
    private int _selectedWorksheet;

    public byte[]? DocxDocument { get => _docxDocument; set => SetField(ref _docxDocument, value); }
    public byte[]? PptxDocument { get => _pptxDocument; set => SetField(ref _pptxDocument, value); }
    public byte[]? XlsxDocument { get => _xlsxDocument; set => SetField(ref _xlsxDocument, value); }
    public byte[]? PdfDocument { get => _pdfDocument; set => SetField(ref _pdfDocument, value); }
    public int SelectedWorksheet { get => _selectedWorksheet; set => SetField(ref _selectedWorksheet, value); }

    public async Task OpenDocxAsync(string path) => DocxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenPptxAsync(string path) => PptxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenXlsxAsync(string path) => XlsxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenPdfAsync(string path) => PdfDocument = await File.ReadAllBytesAsync(path);

    public void ReleaseDocuments()
    {
        // null automatically cancels loading and releases each viewer's resources.
        DocxDocument = null;
        PptxDocument = null;
        XlsxDocument = null;
        PdfDocument = null;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    private void SetField<T>(ref T field, T value, [CallerMemberName] string? name = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return;
        field = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Document、PageCount、SheetCount 是 Avalonia StyledProperty。请在 ViewModel 中将文档字节数组绑定到 Document;需要释放内存时也将绑定源设为 null,使控件和 ViewModel 都不再保留该字节数组。

可在代码中调用 LoadAsync(Stream) 读取流。控件不会关闭调用方传入的流,而会创建自己的字节快照并将其赋给 Document;MVVM 绑定仍建议使用 byte[]? Document。

NativeAOT

本包支持 NativeAOT。

格式范围与限制

  • DOCX:WordprocessingML 段落、文字 Run、编号、图片、表格、常见形状/文本框和页面流式布局。
  • PPTX:PresentationML 幻灯片、主题/样式继承、文字、图片、填充、渐变、常见形状及已支持图表的连续流布局。
  • XLSX:工作簿/工作表关系、共享字符串/富文本、样式、合并单元格、图片、行列尺寸、颜色和当前工作表绑定。
  • PDF:压缩对象流、Form XObject、文字/CMap 解码、带常见蒙版的图片、填充/线条/透明度,以及 WPS 水印标记。加密、签名、损坏文件或高级 PDF 图形/字体仍可能需要完整 PDF 渲染器,本包不会宣称完全兼容。

English

OfficeViewer.Avalonia is a set of read-only native Avalonia viewers for DOCX, PPTX, XLSX, and common PDF files. Documents use continuous scrolling rather than a flip-book UI.

The outer viewer surface is transparent. Hosts own the surrounding background, corner radius, and shadow by wrapping the control in a Border, Panel, or theme container.

Reference project

The file-reading flow, relationship parsing, style models, and continuous-layout design for DOCX, PPTX, and XLSX are informed by vue-office-core. This package ports those ideas to C# Open XML parsing and Avalonia-native rendering. It does not bundle Vue, JavaScript, or a WebView, and it is not a wrapper around Vue components.

The PDF viewer is this project's separate managed common-subset implementation. It does not bundle PDF.js, PDFium, or PdfPig. See “Format scope and limitations” for the supported subset.

Included controls

Document Namespace and control Result count
Word / DOCX OfficeViewer.Avalonia.Docx.DocxViewer PageCount
PowerPoint / PPTX OfficeViewer.Avalonia.Pptx.PptxViewer PageCount
Excel / XLSX OfficeViewer.Avalonia.Xlsx.XlsxViewer SheetCount, SelectedSheetIndex
PDF OfficeViewer.Avalonia.Pdf.PdfViewer PageCount

预览截图 / Screenshots

以下截图来自 samples 目录中的实际控件运行效果。 / The following screenshots show the viewers running with the sample documents in the samples directory.

格式 / Format 预览 / Preview
Word / DOCX DOCX preview
PowerPoint / PPTX PPTX preview
Excel / XLSX XLSX preview
PDF PDF preview

Every viewer exposes a bindable byte[]? Document property. Assign a new document byte array to start loading automatically; clear it or assign null to cancel stale loading and release the current document model, images, and visual resources. PPTX and PDF only materialize visible pages/slides plus a small adjacent buffer. LoadAsync remains available as a convenience method for non-binding scenarios.

Zoom

All four viewers support Ctrl + mouse wheel zoom, one-finger touch panning in both directions, and two-finger pinch zoom. Panning is available when content exceeds the viewport; the remaining finger can continue panning after a pinch.

Install

Install from your NuGet source:

<PackageReference Include="OfficeViewer.Avalonia" Version="0.1.6" />

For a local build of this repository, add the following folder as a NuGet source:

OfficeViewer.Avalonia.NuGet\artifacts\packages

Avalonia XAML usage

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:docx="clr-namespace:OfficeViewer.Avalonia.Docx;assembly=OfficeViewer.Avalonia"
        xmlns:pptx="clr-namespace:OfficeViewer.Avalonia.Pptx;assembly=OfficeViewer.Avalonia"
        xmlns:xlsx="clr-namespace:OfficeViewer.Avalonia.Xlsx;assembly=OfficeViewer.Avalonia"
        xmlns:pdf="clr-namespace:OfficeViewer.Avalonia.Pdf;assembly=OfficeViewer.Avalonia">
  <Grid RowDefinitions="Auto,*">
    <TextBlock Text="{Binding PageCount, ElementName=DocxPreview}" />
    <Border Grid.Row="1" Background="White" Padding="8">
      <docx:DocxViewer x:Name="DocxPreview"
                       Document="{Binding DocxDocument}" />
    </Border>
  </Grid>
</Window>

Create the other controls in the same way:

<pptx:PptxViewer x:Name="PptxPreview"
                 Document="{Binding PptxDocument}" />
<pdf:PdfViewer x:Name="PdfPreview"
               Document="{Binding PdfDocument}" />
<xlsx:XlsxViewer x:Name="XlsxPreview"
                 Document="{Binding XlsxDocument}"
                 SelectedSheetIndex="{Binding SelectedWorksheet, Mode=TwoWay}" />

SelectedSheetIndex is zero-based. The XLSX control intentionally has no built-in worksheet selector; bind it to your own buttons, ComboBox, tabs, or view model. SheetCount updates after a successful workbook load.

Load and release in C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public sealed class OfficePreviewViewModel : INotifyPropertyChanged
{
    private byte[]? _docxDocument;
    private byte[]? _pptxDocument;
    private byte[]? _xlsxDocument;
    private byte[]? _pdfDocument;
    private int _selectedWorksheet;

    public byte[]? DocxDocument { get => _docxDocument; set => SetField(ref _docxDocument, value); }
    public byte[]? PptxDocument { get => _pptxDocument; set => SetField(ref _pptxDocument, value); }
    public byte[]? XlsxDocument { get => _xlsxDocument; set => SetField(ref _xlsxDocument, value); }
    public byte[]? PdfDocument { get => _pdfDocument; set => SetField(ref _pdfDocument, value); }
    public int SelectedWorksheet { get => _selectedWorksheet; set => SetField(ref _selectedWorksheet, value); }

    public async Task OpenDocxAsync(string path) => DocxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenPptxAsync(string path) => PptxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenXlsxAsync(string path) => XlsxDocument = await File.ReadAllBytesAsync(path);
    public async Task OpenPdfAsync(string path) => PdfDocument = await File.ReadAllBytesAsync(path);

    public void ReleaseDocuments()
    {
        // null automatically cancels loading and releases each viewer's resources.
        DocxDocument = null;
        PptxDocument = null;
        XlsxDocument = null;
        PdfDocument = null;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    private void SetField<T>(ref T field, T value, [CallerMemberName] string? name = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return;
        field = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Document, PageCount, and SheetCount are Avalonia styled properties. Bind the document byte array from a view model to Document; set that binding source to null when releasing memory so neither the viewer nor the view model retains the bytes.

For code-behind or service code, LoadAsync(Stream) accepts a stream without taking ownership of it. The viewer creates its own byte snapshot and assigns it to Document; byte[]? Document remains the recommended MVVM binding API.

NativeAOT

This package supports NativeAOT.

Format scope and limitations

  • DOCX: WordprocessingML paragraphs, runs, numbering, images, tables, common shapes/text boxes, and page-flow layout.
  • PPTX: PresentationML slides, theme/style inheritance, text, pictures, fills, gradients, common shapes, and supported charts in continuous flow.
  • XLSX: workbook/sheet relationships, shared strings/rich text, styles, merged cells, images, row/column sizes, colors, and active-sheet binding.
  • PDF: compressed object streams, Form XObjects, text/CMap decoding, images with common masks, fills/lines/transparency, and WPS watermark artifacts. Password-protected, signed, malformed, or advanced PDF graphics/font features can still require a full PDF renderer and are intentionally not claimed as fully supported.

Layout

OfficeViewer.Avalonia.NuGet/
  src/OfficeViewer.Avalonia/       Package source / 包源码
  samples/PackageConsumer/         PackageReference-only consumer / 独立消费项目
  scripts/pack-and-verify.ps1      Package verification / 打包验证
  artifacts/packages/              Generated .nupkg and .snupkg files / 生成包

0.1.6 更新 / Changes

  • 触屏:统一四个控件的单指拖动与双指缩放,保留缩放中心,修复松开一指后不能继续拖动。
  • PPTX:保持原始图文层级,支持图片裁剪,补充母版/版式静态元素及占位符位置继承,分别应用每段文字的对齐。
  • DOCX:按段内分页标记拆分页面、支持直接设置的段前分页,保留离屏页已测量的高度,读取表格列宽与显式取消加粗/斜体。
  • XLSX:修正数字/布尔值默认对齐、单元格缩小规则、图片锚点与裁剪;切换工作表时取消旧任务并释放图像。
  • 解码任务限制为最多两个并发;离屏页面取消待完成任务。控件创建和文字测量仍需在 UI 线程执行,并分批让出 UI 线程。

Touch pan/pinch transitions are shared by all four viewers. PPTX preserves paint order, picture cropping and static master/layout elements, with placeholder bounds inheritance and per-paragraph alignment. DOCX improves explicit page breaks, retained page heights, table column ratios and explicit font toggles. XLSX improves general alignment, shrink-to-fit, image anchors/cropping and asynchronous sheet replacement. Image decoding is limited to two concurrent workers; obsolete page jobs are canceled. Native controls and text layout are still created on the UI thread in batches.

实现继续参考本地 vue-office-core 的 DOCX 包装层、ExcelJS 转换与图片锚点逻辑,以及 PPTX 使用的 pptx-preview 思路。列宽和图片裁剪同时参考 Open XML 列宽说明 和 DrawingML srcRect 说明。列宽当前按 Calibri 11 的最大数字宽度进行换算,其他默认字体可能存在差异。复杂形状、图表、自动分页及字体替换仍不保证与 Office/WPS 完全一致。

The implementation continues to reference vue-office-core and its underlying preview libraries, supplemented by the Open XML column-width and DrawingML source-rectangle specifications linked above. Column widths currently use the Calibri 11 maximum-digit-width fallback; other Normal fonts can differ. Complex shapes/charts, automatic pagination and font substitution are not guaranteed to match Office/WPS exactly.

回归检查 / Regression checks:

dotnet run --project tests/OfficeViewer.Regression -c Release

回归包含 Avalonia 原始触摸事件、解析/渲染断言、快速切表、取消加载和样例滚动检查;桌面测试不能替代 Android 真机验证。

Checks cover raw Avalonia touch input, parser/render assertions, rapid sheet switching, canceled loads and sample scrolling. Desktop tests do not replace Android device validation.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.6 151 9/20/2026
0.1.5 135 9/1/2026
0.1.2 136 8/5/2026
0.1.1 117 8/5/2026
0.1.0 135 8/5/2026 0.1.0 is deprecated because it has critical bugs.

修复单指滚动与双指缩放切换;改进 PPTX 层级、裁剪与版式继承,DOCX 分页和表格列宽,XLSX 图片锚点、对齐与异步切表;取消离屏任务并限制图片解码并发。Fix touch pan/pinch transitions; improve PPTX paint order, cropping and layout inheritance, DOCX breaks and table widths, and XLSX anchors, alignment and async sheet switching; cancel offscreen work and bound image decoding.