Back to skills
extension
Category: Development & EngineeringNo API key required

xaf-office

XAF Office/Document Management Modules - FileAttachmentsModule with IFileData/FileAttachment patterns (XPO and EF Core), SpreadsheetModule for Excel editing with ISpreadsheetValueStorage, RichTextModule for Word-like editing with IRichTextDocumentProvider and mail merge, PdfViewerModule for PDF display, platform differences (Blazor vs WinForms), programmatic document manipulation. Use when adding file attachments, spreadsheet editing, rich text editing, or PDF viewing to DevExpress XAF applications.

personAuthor: 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