返回 Skill 列表
extension
分类: 开发与工程无需 API Key

xaf-office

XAF办公/文档管理模块 - FileAttachmentsModule支持IFileData/FileAttachment模式(XPO和EF Core),SpreadsheetModule通过ISpreadsheetValueStorage支持Excel编辑,RichTextModule通过IRichTextDocumentProvider支持类似Word的编辑及邮件合并功能,PdfViewerModule用于PDF显示,平台差异(Blazor与WinForms),程序化文档操作。当需要向DevExpress XAF应用程序中添加文件附件、电子表格编辑、富文本编辑或PDF查看时使用。

person作者: jakexiaohubgithub

XAF: Office / Document Management Modules

Available Modules

| Module | Class | File Type | Platforms | |---|---|---|---| | File Attachments | FileAttachmentsModule | any file | Blazor, WinForms | | Spreadsheet | SpreadsheetModule | .xlsx | Blazor, WinForms | | Rich Text | RichTextModule | .docx, .rtf | Blazor, WinForms | | PDF Viewer | PdfViewerModule | .pdf | Blazor, WinForms |


File Attachments Module

NuGet Packages

<PackageReference Include="DevExpress.ExpressApp.FileAttachments" Version="25.1.*" />
<PackageReference Include="DevExpress.ExpressApp.FileAttachments.Blazor" Version="25.1.*" />
<!-- or for WinForms: -->
<PackageReference Include="DevExpress.ExpressApp.FileAttachments.Win" Version="25.1.*" />

Setup

// Module:
RequiredModuleTypes.Add(typeof(FileAttachmentsModule));

// Blazor Program.cs:
b.AddModule<FileAttachmentsModule>();
b.AddModule<FileAttachmentsBlazorModule>();

IFileData Interface

public interface IFileData {
    string FileName { get; set; }
    int Size { get; }
    void LoadFromStream(string fileName, Stream stream);
    void SaveToStream(Stream stream);
}

XPO Pattern — Single File Attachment

// Option 1: Built-in FileData (recommended)
using DevExpress.Persistent.BaseImpl;

public class Document : BaseObject {
    public Document(Session session) : base(session) { }

    private FileData attachment;
    [Aggregated]
    public FileData Attachment {
        get => attachment;
        set => SetPropertyValue(nameof(Attachment), ref attachment, value);
    }

    // EditorAlias auto-detected from IFileData
}

EF Core Pattern — Single File Attachment

using DevExpress.Persistent.BaseImpl.EF;

public class Document : BaseObject {
    // FileAttachment is the EF Core equivalent of FileData
    public virtual FileAttachment Attachment { get; set; }
}

// DbContext:
public DbSet<FileAttachment> FileAttachments { get; set; }

XPO Pattern — Multiple File Attachments (Collection)

public class Employee : BaseObject {
    public Employee(Session session) : base(session) { }

    [Aggregated]
    [Association("Employee-Documents")]
    public XPCollection<FileData> Documents => GetCollection<FileData>(nameof(Documents));
}

EF Core Pattern — Multiple Files

public class Employee : BaseObject {
    public virtual IList<FileAttachment> Documents { get; set; }
        = new ObservableCollection<FileAttachment>();
}

Programmatic File Access

// Load from stream
var attachment = objectSpace.CreateObject<FileData>();
using (var stream = File.OpenRead("report.pdf")) {
    attachment.LoadFromStream("report.pdf", stream);
}
employee.Attachment = attachment;
objectSpace.CommitChanges();

// Save to stream
using (var stream = new MemoryStream()) {
    employee.Attachment.SaveToStream(stream);
    File.WriteAllBytes("output.pdf", stream.ToArray());
}

Spreadsheet Module

Setup

<PackageReference Include="DevExpress.ExpressApp.Spreadsheet" Version="25.1.*" />
<PackageReference Include="DevExpress.ExpressApp.Spreadsheet.Blazor" Version="25.1.*" />
b.AddModule<SpreadsheetModule>();
b.AddModule<SpreadsheetBlazorModule>();

Business Object with Embedded Spreadsheet

// XPO
public class Budget : BaseObject {
    public Budget(Session session) : base(session) { }

    // Store spreadsheet as byte array
    private byte[] spreadsheetData;
    [EditorAlias("SpreadsheetPropertyEditor")]
    [Size(SizeAttribute.Unlimited)]
    public byte[] SpreadsheetData {
        get => spreadsheetData;
        set => SetPropertyValue(nameof(SpreadsheetData), ref spreadsheetData, value);
    }
}

// EF Core
public class Budget : BaseObject {
    [EditorAlias("SpreadsheetPropertyEditor")]
    public virtual byte[] SpreadsheetData { get; set; }
}

Programmatic Spreadsheet Manipulation

using DevExpress.Spreadsheet;

// Read spreadsheet data from XAF object
byte[] data = budget.SpreadsheetData;
using var workbook = new Workbook();
using var stream = new MemoryStream(data);
workbook.LoadDocument(stream, DocumentFormat.Xlsx);

var sheet = workbook.Worksheets[0];
sheet.Cells["B2"].Value = 1234.56;
sheet.Cells["B3"].Formula = "=B2*1.23";

// Save back
using var outputStream = new MemoryStream();
workbook.SaveDocument(outputStream, DocumentFormat.Xlsx);
budget.SpreadsheetData = outputStream.ToArray();
objectSpace.CommitChanges();

Rich Text Module

Setup

<PackageReference Include="DevExpress.ExpressApp.RichTextEdit" Version="25.1.*" />
<PackageReference Include="DevExpress.ExpressApp.RichTextEdit.Blazor" Version="25.1.*" />
b.AddModule<RichTextEditModule>();
b.AddModule<RichTextEditBlazorModule>();

Business Object with Rich Text

// XPO
public class Article : BaseObject {
    public Article(Session session) : base(session) { }

    private byte[] content;
    [EditorAlias("RichTextPropertyEditor")]
    [Size(SizeAttribute.Unlimited)]
    public byte[] Content {
        get => content;
        set => SetPropertyValue(nameof(Content), ref content, value);
    }
}

// EF Core
public class Article : BaseObject {
    [EditorAlias("RichTextPropertyEditor")]
    public virtual byte[] Content { get; set; }
}

Mail Merge

using DevExpress.XtraRichEdit;
using DevExpress.XtraRichEdit.API.Native;

// Load template from byte[] stored in XAF object
using var server = new RichEditDocumentServer();
using var templateStream = new MemoryStream(article.Content);
server.LoadDocument(templateStream, DocumentFormat.OpenXml);

// Execute mail merge
server.Document.MailMerge.DataSource = contacts; // your data list
server.Document.MailMerge.Execute();

// Export result
using var outputStream = new MemoryStream();
server.SaveDocument(outputStream, DocumentFormat.OpenXml);
var mergedBytes = outputStream.ToArray();

PDF Viewer Module

Setup

<PackageReference Include="DevExpress.ExpressApp.PdfViewer" Version="25.1.*" />
<PackageReference Include="DevExpress.ExpressApp.PdfViewer.Blazor" Version="25.1.*" />
b.AddModule<PdfViewerModule>();
b.AddModule<PdfViewerBlazorModule>();

Business Object with PDF

// XPO
public class Contract : BaseObject {
    public Contract(Session session) : base(session) { }

    private byte[] pdfContent;
    [EditorAlias("PdfViewerPropertyEditor")]
    [Size(SizeAttribute.Unlimited)]
    public byte[] PdfContent {
        get => pdfContent;
        set => SetPropertyValue(nameof(PdfContent), ref pdfContent, value);
    }
}

Blazor vs WinForms Differences

| Feature | Blazor | WinForms | |---|---|---| | File upload | DxUpload component | OpenFileDialog | | Spreadsheet editor | Browser-based DevExpress Spreadsheet | XtraSpreadsheet (Win control) | | Rich text editor | Browser-based Rich Text editor | XtraRichEdit (Win control) | | PDF viewer | Browser-based PDF viewer | XtraPdfViewer (Win control) | | Module class | *BlazorModule | *WindowsFormsModule |


Auto-Added Document Actions

When an Office module property is present in Detail View, XAF automatically adds:

  • Save (document) action
  • Export / Print action (module-dependent)
  • Load (from file) action

No extra controller code needed for basic file operations.


Source Links

  • Document Management: https://docs.devexpress.com/eXpressAppFramework/113986/document-management
  • File Attachments: https://docs.devexpress.com/eXpressAppFramework/113549/document-management/file-attachments-module
  • Spreadsheet: https://docs.devexpress.com/eXpressAppFramework/400552/document-management/spreadsheet-document
  • Rich Text: https://docs.devexpress.com/eXpressAppFramework/400315/document-management/rich-text-document
  • FileData (XPO): https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.BaseImpl.FileData
  • FileAttachment (EF Core): https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.BaseImpl.EF.FileAttachment
  • IFileData API: https://docs.devexpress.com/eXpressAppFramework/DevExpress.Persistent.Base.IFileData