VintaSoft Imaging .NET SDK v8.6
In This Topic
    PDF: PDF Portfolio (Attachments)
    In This Topic

    Beginning with PDF 1.7, PDF documents can specify how a viewer application's user interface presents collections of file attachments (Portfolio), where the attachments are related in structure or content. Such a presentation is called a portable collection. The intent of portable collections is to present, sort, and search collections of related documents, such as email archives, photo collections, and etc. If attachment is present in a PDF document, the user interface presents the document as an attachment collection.

    Beginning with PDF 1.7 Extension Level 3, an attachment collection can contain a folders for the purpose of organizing files into a hierarchical structure.

    VintaSoft PDF .NET Plug-in allows to:



    Porfolio management using VintaSoft PDF .NET Plug-in.

    The new empty attachment collection (portfolio) of PDF document can be created using PdfDocument.CreateAttachments method.

    The current attachment collection (portfolio) of PDF document and related data structures can be removed using PdfDocument.RemoveAttachments method.

    The attachments collection (portfolio) can be accessed using PdfDocument.Attachments property.

    Here is a list of the main properties and methods used for management of attachment collection:


    Visual appearance settings of PDF viewer application related with portfolio.

    For the visual appearance of PDF viewer application are responsible the following properties:


    Portfolio Schema.

    Schema of attachement collection (PdfAttachmentCollection.Schema) defines data columns in the DetailsMode view mode.

    The schema is represented by PdfAttachmentCollectionSchema class and is a dictionary, which puts each name of schema field in correspondence with an object of type PdfAttachmentCollectionSchemaField. Object of PdfAttachmentCollectionSchemaField class describes type and parameters of data column in DetailsMode view mode:
    Data, displayed in the column, is defined by PdfAttachmentCollectionSchemaField.DataType property:
    The data of field types AttachmentCollectionSchemaFieldDataType.String, AttachmentCollectionSchemaFieldDataType.Date and AttachmentCollectionSchemaFieldDataType.Number is stored in the data field dictionary (PdfAttachmentDataFieldCollection) of an appropriate folder or file:
    The key in the data fields dictionary is the name of the appropriate field of data schema (i.e. the key is in PdfAttachmentCollection.Schema dictionary).

    The data of data field can be obtained using the following methods:
    The data of data field can be specified using the following methods:

    Here is an example that shows how to create the portfolio schema:

    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <summary>
    ''' Creates new PDF document with portfolio and portfolio schema:
    ''' </summary>
    ''' <param name="outputPdfFilename">The output PDF filename.</param>
    Public Shared Sub TestPdfAttachmentCollectionSchema(outputPdfFilename As String)
        ' create PDF document (version 1.7)
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(outputPdfFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17)
            ' add page to PDF document
            Dim page As Vintasoft.Imaging.Pdf.Tree.PdfPage = document.Pages.Add(Vintasoft.Imaging.PaperSizeKind.A4)
    
            ' draw text on first page
            Using g As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = page.GetGraphics()
                Dim textBox As New Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure()
                textBox.Font = document.FontManager.GetStandardFont(Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman)
                textBox.FontSize = 30
                textBox.Location = New System.Drawing.PointF(0, 0)
                textBox.Size = page.MediaBox.Size
                textBox.TextAlignment = Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Top Or Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Left Or Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Right
                textBox.TextBrush = New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black)
                textBox.Text = "This document is Portfolio" & vbLf & "(Attachment Collection)" & vbLf & "To view Portfolio you should use PDF viewer compatible with PDF 1.7 ExtensionLevel 3."
                textBox.Draw(g)
            End Using
    
            ' create attachements
            document.CreateAttachments(True)
    
            ' set viewer settings
            document.Attachments.View = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionViewMode.DetailsMode
            document.Attachments.SplitterBar = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar(document)
            document.Attachments.SplitterBar.Direction = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSplitterBarDirection.None
            document.DocumentViewMode = Vintasoft.Imaging.Pdf.PdfDocumentViewMode.UseAttachments
    
            ' create folder and files
            Dim folder1 As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder = document.Attachments.RootFolder.AddFolder("Folder1")
            folder1.CreationDate = System.DateTime.Now
            Dim file1 As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification = AddFile(document.Attachments.RootFolder, "File1.txt", "Test File1")
            file1.CreationDate = System.DateTime.Now
            Dim file2 As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification = AddFile(document.Attachments.RootFolder, "File2.txt", "Test File2")
            file2.CreationDate = System.DateTime.Now
    
    
            ' create portfolio schema
            document.Attachments.Schema = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema(document)
    
            ' "File Name" column
            document.Attachments.Schema.Add("Filename", New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "File Name", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Filename))
            document.Attachments.Schema("Filename").Order = 0
    
            ' "Uncompressed Size" column
            document.Attachments.Schema.Add("UncompressedSize", New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Uncompressed Size", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.UncompressedSize))
            document.Attachments.Schema("UncompressedSize").Order = 1
    
            ' "Creation Date" column
            document.Attachments.Schema.Add("CreationDate", New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Creation Date", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.CreationDate))
            document.Attachments.Schema("CreationDate").Order = 2
    
            ' "Description" column
            document.Attachments.Schema.Add("Description", New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Description", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.FileDescription))
            document.Attachments.Schema("Description").Order = 3
            ' set Description field as editable
            document.Attachments.Schema("Description").IsSupportsEditing = True
    
            ' "UserName" custom column (string data)
            Dim userNameFieldName As String = "adobe:UserName"
            document.Attachments.Schema.Add(userNameFieldName, New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "User Name", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.[String]))
            document.Attachments.Schema(userNameFieldName).Order = 4
            ' disable editing of UserName field
            document.Attachments.Schema(userNameFieldName).IsSupportsEditing = False
    
            ' invisible schema field that is used for sorting attachment collection items
            Dim orderFieldName As String = "Order"
            document.Attachments.Schema.Add(orderFieldName, New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Order", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Number))
            document.Attachments.Schema(orderFieldName).Order = 5
            document.Attachments.Schema(orderFieldName).IsVisible = False
    
            ' specify the sorting order: first sort by "Order" field, second sort by "Filename" field
            document.Attachments.Sort = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort(document)
            document.Attachments.Sort.FieldNames = New String() {orderFieldName, "Filename"}
    
    
            ' create data fields of Folder1
            folder1.DataFields = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document)
            folder1.DataFields.Add(userNameFieldName, "User of Folder1")
            folder1.DataFields.Add(orderFieldName, 0)
    
            ' create data fields of File1
            file1.DataFields = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document)
            file1.DataFields.Add(userNameFieldName, "User of File1")
            file1.DataFields.Add(orderFieldName, 1)
    
            ' create data fields of File2
            file2.DataFields = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document)
            file2.DataFields.Add(userNameFieldName, "User of File2")
            file2.DataFields.Add(orderFieldName, 2)
    
            ' set descriptions
            folder1.Description = "Is empty folder."
            file1.Description = "Description of File1"
            file2.Description = "Description of File2"
    
    
            ' save changes in PDF document
            document.SaveChanges()
        End Using
    End Sub
    
    ''' <summary>
    ''' Adds the file to specified portfolio folder.
    ''' </summary>
    ''' <param name="folder">The portfolio folder.</param>
    ''' <param name="filename">The filename.</param>
    ''' <param name="fileContent">Content of the file.</param>
    ''' <returns>Embedded file specification that contains added file.</returns>
    Private Shared Function AddFile(folder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder, filename As String, fileContent As String) As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification
        Using stream As New System.IO.MemoryStream()
            Using writer As System.IO.TextWriter = New System.IO.StreamWriter(stream)
                writer.Write(fileContent)
                writer.Flush()
                stream.Position = 0
                Dim embeddedFile As New Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile(folder.Document, stream)
                Return folder.AddFile(embeddedFile, filename)
            End Using
        End Using
    End Function
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <summary>
    /// Creates new PDF document with portfolio and portfolio schema:
    /// </summary>
    /// <param name="outputPdfFilename">The output PDF filename.</param>
    public static void TestPdfAttachmentCollectionSchema(string outputPdfFilename)
    {
        // create PDF document (version 1.7)
        using (Vintasoft.Imaging.Pdf.PdfDocument document =
            new Vintasoft.Imaging.Pdf.PdfDocument(outputPdfFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17))
        {
            // add page to PDF document
            Vintasoft.Imaging.Pdf.Tree.PdfPage page = document.Pages.Add(Vintasoft.Imaging.PaperSizeKind.A4);
    
            // draw text on first page
            using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics g = page.GetGraphics())
            {
                Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure textBox =
                    new Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure();
                textBox.Font = document.FontManager.GetStandardFont(
                    Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman);
                textBox.FontSize = 30;
                textBox.Location = new System.Drawing.PointF(0, 0);
                textBox.Size = page.MediaBox.Size;
                textBox.TextAlignment =
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Top |
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Left |
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Right;
                textBox.TextBrush = new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black);
                textBox.Text = "This document is Portfolio\n(Attachment Collection)\nTo view Portfolio you should use PDF viewer compatible with PDF 1.7 ExtensionLevel 3.";
                textBox.Draw(g);
            }
    
            // create attachements
            document.CreateAttachments(true);
    
            // set viewer settings
            document.Attachments.View = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionViewMode.DetailsMode;
            document.Attachments.SplitterBar = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar(document);
            document.Attachments.SplitterBar.Direction = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSplitterBarDirection.None;
            document.DocumentViewMode = Vintasoft.Imaging.Pdf.PdfDocumentViewMode.UseAttachments;
    
            // create folder and files
            Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder folder1 = document.Attachments.RootFolder.AddFolder("Folder1");
            folder1.CreationDate = System.DateTime.Now;
            Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification file1 = AddFile(document.Attachments.RootFolder, "File1.txt", "Test File1");
            file1.CreationDate = System.DateTime.Now;
            Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification file2 = AddFile(document.Attachments.RootFolder, "File2.txt", "Test File2");
            file2.CreationDate = System.DateTime.Now;
    
    
            // create portfolio schema
            document.Attachments.Schema =
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema(document);
    
            // "File Name" column
            document.Attachments.Schema.Add("Filename",
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "File Name",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Filename));
            document.Attachments.Schema["Filename"].Order = 0;
    
            // "Uncompressed Size" column
            document.Attachments.Schema.Add("UncompressedSize",
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Uncompressed Size",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.UncompressedSize));
            document.Attachments.Schema["UncompressedSize"].Order = 1;
    
            // "Creation Date" column
            document.Attachments.Schema.Add("CreationDate",
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Creation Date",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.CreationDate));
            document.Attachments.Schema["CreationDate"].Order = 2;
    
            // "Description" column
            document.Attachments.Schema.Add("Description",
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Description",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.FileDescription));
            document.Attachments.Schema["Description"].Order = 3;
            // set Description field as editable
            document.Attachments.Schema["Description"].IsSupportsEditing = true;
    
            // "UserName" custom column (string data)
            string userNameFieldName = "adobe:UserName";
            document.Attachments.Schema.Add(userNameFieldName,
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "User Name",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.String));
            document.Attachments.Schema[userNameFieldName].Order = 4;
            // disable editing of UserName field
            document.Attachments.Schema[userNameFieldName].IsSupportsEditing = false;
    
            // invisible schema field that is used for sorting attachment collection items
            string orderFieldName = "Order";
            document.Attachments.Schema.Add(orderFieldName,
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Order",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Number));
            document.Attachments.Schema[orderFieldName].Order = 5;
            document.Attachments.Schema[orderFieldName].IsVisible = false;
    
            // specify the sorting order: first sort by "Order" field, second sort by "Filename" field
            document.Attachments.Sort = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort(document);
            document.Attachments.Sort.FieldNames = new string[] { orderFieldName, "Filename" };
    
    
            // create data fields of Folder1
            folder1.DataFields = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document);
            folder1.DataFields.Add(userNameFieldName, "User of Folder1");
            folder1.DataFields.Add(orderFieldName, 0);
    
            // create data fields of File1
            file1.DataFields = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document);
            file1.DataFields.Add(userNameFieldName, "User of File1");
            file1.DataFields.Add(orderFieldName, 1);
    
            // create data fields of File2
            file2.DataFields = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(document);
            file2.DataFields.Add(userNameFieldName, "User of File2");
            file2.DataFields.Add(orderFieldName, 2);
    
            // set descriptions
            folder1.Description = "Is empty folder.";
            file1.Description = "Description of File1";
            file2.Description = "Description of File2";
    
    
            // save changes in PDF document
            document.SaveChanges();
        }
    }
    
    /// <summary>
    /// Adds the file to specified portfolio folder.
    /// </summary>
    /// <param name="folder">The portfolio folder.</param>
    /// <param name="filename">The filename.</param>
    /// <param name="fileContent">Content of the file.</param>
    /// <returns>Embedded file specification that contains added file.</returns>
    private static Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification AddFile(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder folder,
        string filename,
        string fileContent)
    {
        using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
        {
            using (System.IO.TextWriter writer = new System.IO.StreamWriter(stream))
            {
                writer.Write(fileContent);
                writer.Flush();
                stream.Position = 0;
                Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile embeddedFile =
                    new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile(folder.Document, stream);
                return folder.AddFile(embeddedFile, filename);
            }
        }
    }
                    
    



    Examples.

    Here is an example that shows how to get information about attachments of PDF document:

    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging.Pdf
    
    ''' <summary>
    ''' Prints the portfolio structure.
    ''' </summary>
    ''' <param name="pdfFilename">The PDF filename.</param>
    Public Shared Sub PrintPortfolioStructure(pdfFilename As String)
        ' open PDF document in read-only mode
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename, True)
            ' if PDF document does not contain portfolio
            If document.Attachments Is Nothing Then
                System.Console.WriteLine("Document does not have attachments (portfolio).")
                Return
            End If
    
            ' print initial view mode
            System.Console.WriteLine(String.Format("Initial View Mode = {0}", document.Attachments.View))
    
            ' print colors information
            If document.Attachments.Colors IsNot Nothing Then
                PrintPortfolioColors(document.Attachments.Colors)
            End If
    
            ' print portfolio schema
            If document.Attachments.Schema IsNot Nothing Then
                PrintPortfolioSchema(document.Attachments.Schema)
            End If
    
            ' print portfolio sort settings
            If document.Attachments.Sort IsNot Nothing Then
                PrintPortfolioSort(document.Attachments.Sort)
            End If
    
            ' print portfolio splitter bar settings
            If document.Attachments.SplitterBar IsNot Nothing Then
                PrintPortfolioSplitterBar(document.Attachments.SplitterBar)
            End If
    
            ' print portfolio folders and files
            If document.Attachments.RootFolder IsNot Nothing Then
                System.Console.WriteLine("Folder structure:")
                PrintFolderStructure(document.Attachments.RootFolder, "  ")
            Else
                System.Console.WriteLine("Files:")
                PrintFileInfo(document.Attachments.GetFiles(""), "  ")
            End If
        End Using
    End Sub
    
    ''' <summary>
    ''' Prints the folder structure.
    ''' </summary>
    ''' <param name="folder">The PDF attachment folder.</param>
    ''' <param name="padding">Padding.</param>
    Private Shared Sub PrintFolderStructure(folder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder, padding As String)
        System.Console.WriteLine(String.Format("{0}Folder: {1}", padding, folder.Name))
        padding += "  "
        PrintFileInfo(folder.Files, padding)
        Dim subFolders As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder() = folder.Folders
        If subFolders IsNot Nothing Then
            For Each subFolder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder In subFolders
                PrintFolderStructure(subFolder, padding)
            Next
        End If
    End Sub
    
    ''' <summary>
    ''' Prints the portfolio splitter bar information.
    ''' </summary>
    ''' <param name="splitterBar">The splitter bar.</param>
    Private Shared Sub PrintPortfolioSplitterBar(splitterBar As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar)
        System.Console.WriteLine("Splitter Bar:")
        System.Console.WriteLine(String.Format("  Direction = {0}", splitterBar.Direction))
        System.Console.WriteLine(String.Format("  Position  = {0}", splitterBar.Position))
    End Sub
    
    ''' <summary>
    ''' Prints an information for specified files.
    ''' </summary>
    ''' <param name="fileSpecs">The PDF embedded file specifications.</param>
    ''' <param name="padding">Padding.</param>
    Private Shared Sub PrintFileInfo(fileSpecs As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification(), padding As String)
        For Each fileSpec As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification In fileSpecs
            System.Console.WriteLine(String.Format("{0}File: {1}", padding, fileSpec.Filename))
            System.Console.WriteLine(String.Format("{0}  CompressedSize   = {1}", padding, fileSpec.CompressedSize))
            System.Console.WriteLine(String.Format("{0}  UncompressedSize = {1}", padding, fileSpec.UncompressedSize))
            System.Console.WriteLine(String.Format("{0}  Compression      = {1}", padding, fileSpec.Compression))
            System.Console.WriteLine(String.Format("{0}  CreationDate     = {1}", padding, fileSpec.CreationDate))
            System.Console.WriteLine(String.Format("{0}  ModificationDate = {1}", padding, fileSpec.ModificationDate))
            System.Console.WriteLine(String.Format("{0}  Description      = {1}", padding, fileSpec.Description))
            System.Console.WriteLine(String.Format("{0}  HasThumbnail     = {1}", padding, fileSpec.Thumbnail IsNot Nothing))
            If fileSpec.DataFields IsNot Nothing Then
                System.Console.WriteLine("    DataFields:")
                For Each name As String In fileSpec.DataFields.Keys
                    System.Console.WriteLine(String.Format("      {0}={1}", name, fileSpec.DataFields(name).DataAsString))
                Next
            End If
        Next
    End Sub
    
    ''' <summary>
    ''' Prints the portfolio sort properties.
    ''' </summary>
    ''' <param name="sort">The PDF attachment collection sort properties.</param>
    Private Shared Sub PrintPortfolioSort(sort As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort)
        System.Console.WriteLine("Sort:")
        System.Console.WriteLine("  Field names:")
        Dim fieldNames As String() = sort.FieldNames
        For i As Integer = 0 To fieldNames.Length - 1
            System.Console.WriteLine("    {0}: {1}", i, fieldNames(i))
        Next
    
        System.Console.WriteLine("  Ascending orders:")
        Dim ascendingOrders As Boolean() = sort.AscendingOrders
        For i As Integer = 0 To ascendingOrders.Length - 1
            System.Console.WriteLine("    {0}: {1}", i, ascendingOrders(i))
        Next
    End Sub
    
    ''' <summary>
    ''' Prints the portfolio schema.
    ''' </summary>
    ''' <param name="schema">The PDF attachment collection schema.</param>
    Private Shared Sub PrintPortfolioSchema(schema As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema)
        System.Console.WriteLine("Schema:")
        For Each key As String In schema.Keys
            System.Console.WriteLine(String.Format("  {0}:", key))
            Dim field As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField = schema(key)
            System.Console.WriteLine("    DataType          = {0}", field.DataType)
            System.Console.WriteLine("    DisplayedName     = {0}", field.DisplayedName)
            System.Console.WriteLine("    IsSupportsEditing = {0}", field.IsSupportsEditing)
            System.Console.WriteLine("    IsVisible         = {0}", field.IsVisible)
            System.Console.WriteLine("    Order             = {0}", field.Order)
        Next
    End Sub
    
    ''' <summary>
    ''' Prints the portfolio colors information.
    ''' </summary>
    ''' <param name="presentationColors">The presentation colors.</param>
    Private Shared Sub PrintPortfolioColors(presentationColors As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfPresentationColors)
        System.Console.WriteLine("Colors:")
        System.Console.WriteLine(String.Format("  Background     = {0}", presentationColors.Background))
        System.Console.WriteLine(String.Format("  CardBackground = {0}", presentationColors.CardBackground))
        System.Console.WriteLine(String.Format("  CardBorder     = {0}", presentationColors.CardBorder))
        System.Console.WriteLine(String.Format("  PrimaryText    = {0}", presentationColors.PrimaryText))
        System.Console.WriteLine(String.Format("  SecondaryText  = {0}", presentationColors.SecondaryText))
    End Sub
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging.Pdf
    
    /// <summary>
    /// Prints the portfolio structure.
    /// </summary>
    /// <param name="pdfFilename">The PDF filename.</param>
    public static void PrintPortfolioStructure(string pdfFilename)
    {
        // open PDF document in read-only mode
        using (Vintasoft.Imaging.Pdf.PdfDocument document =
            new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename, true))
        {
            // if PDF document does not contain portfolio
            if (document.Attachments == null)
            {
                System.Console.WriteLine("Document does not have attachments (portfolio).");
                return;
            }
    
            // print initial view mode
            System.Console.WriteLine(string.Format("Initial View Mode = {0}", document.Attachments.View));
    
            // print colors information
            if (document.Attachments.Colors != null)
                PrintPortfolioColors(document.Attachments.Colors);
    
            // print portfolio schema
            if (document.Attachments.Schema != null)
                PrintPortfolioSchema(document.Attachments.Schema);
    
            // print portfolio sort settings
            if (document.Attachments.Sort != null)
                PrintPortfolioSort(document.Attachments.Sort);
    
            // print portfolio splitter bar settings
            if (document.Attachments.SplitterBar != null)
                PrintPortfolioSplitterBar(document.Attachments.SplitterBar);
    
            // print portfolio folders and files
            if (document.Attachments.RootFolder != null)
            {
                System.Console.WriteLine("Folder structure:");
                PrintFolderStructure(document.Attachments.RootFolder, "  ");
            }
            else
            {
                System.Console.WriteLine("Files:");
                PrintFileInfo(document.Attachments.GetFiles(""), "  ");
            }
        }
    }
    
    /// <summary>
    /// Prints the folder structure.
    /// </summary>
    /// <param name="folder">The PDF attachment folder.</param>
    /// <param name="padding">Padding.</param>
    private static void PrintFolderStructure(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder folder, string padding)
    {
        System.Console.WriteLine(string.Format("{0}Folder: {1}", padding, folder.Name));
        padding += "  ";
        PrintFileInfo(folder.Files, padding);
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder[] subFolders = folder.Folders;
        if (subFolders != null)
        {
            foreach (Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder subFolder in subFolders)
                PrintFolderStructure(subFolder, padding);
        }
    }
    
    /// <summary>
    /// Prints the portfolio splitter bar information.
    /// </summary>
    /// <param name="splitterBar">The splitter bar.</param>
    private static void PrintPortfolioSplitterBar(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar splitterBar)
    {
        System.Console.WriteLine("Splitter Bar:");
        System.Console.WriteLine(string.Format("  Direction = {0}", splitterBar.Direction));
        System.Console.WriteLine(string.Format("  Position  = {0}", splitterBar.Position));
    }
    
    /// <summary>
    /// Prints an information for specified files.
    /// </summary>
    /// <param name="fileSpecs">The PDF embedded file specifications.</param>
    /// <param name="padding">Padding.</param>
    private static void PrintFileInfo(
        Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification[] fileSpecs, string padding)
    {
        foreach (Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification fileSpec in fileSpecs)
        {
            System.Console.WriteLine(string.Format("{0}File: {1}", padding, fileSpec.Filename));
            System.Console.WriteLine(string.Format("{0}  CompressedSize   = {1}", padding, fileSpec.CompressedSize));
            System.Console.WriteLine(string.Format("{0}  UncompressedSize = {1}", padding, fileSpec.UncompressedSize));
            System.Console.WriteLine(string.Format("{0}  Compression      = {1}", padding, fileSpec.Compression));
            System.Console.WriteLine(string.Format("{0}  CreationDate     = {1}", padding, fileSpec.CreationDate));
            System.Console.WriteLine(string.Format("{0}  ModificationDate = {1}", padding, fileSpec.ModificationDate));
            System.Console.WriteLine(string.Format("{0}  Description      = {1}", padding, fileSpec.Description));
            System.Console.WriteLine(string.Format("{0}  HasThumbnail     = {1}", padding, fileSpec.Thumbnail != null));
            if (fileSpec.DataFields != null)
            {
                System.Console.WriteLine("    DataFields:");
                foreach (string name in fileSpec.DataFields.Keys)
                {
                    System.Console.WriteLine(string.Format("      {0}={1}", name,
                        fileSpec.DataFields[name].DataAsString));
                }
            }
        }
    }
    
    /// <summary>
    /// Prints the portfolio sort properties.
    /// </summary>
    /// <param name="sort">The PDF attachment collection sort properties.</param>
    private static void PrintPortfolioSort(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort sort)
    {
        System.Console.WriteLine("Sort:");
        System.Console.WriteLine("  Field names:");
        string[] fieldNames = sort.FieldNames;
        for (int i = 0; i < fieldNames.Length; i++)
            System.Console.WriteLine("    {0}: {1}", i, fieldNames[i]);
    
        System.Console.WriteLine("  Ascending orders:");
        bool[] ascendingOrders = sort.AscendingOrders;
        for (int i = 0; i < ascendingOrders.Length; i++)
            System.Console.WriteLine("    {0}: {1}", i, ascendingOrders[i]);
    }
    
    /// <summary>
    /// Prints the portfolio schema.
    /// </summary>
    /// <param name="schema">The PDF attachment collection schema.</param>
    private static void PrintPortfolioSchema(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema schema)
    {
        System.Console.WriteLine("Schema:");
        foreach (string key in schema.Keys)
        {
            System.Console.WriteLine(string.Format("  {0}:", key));
            Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField field = schema[key];
            System.Console.WriteLine("    DataType          = {0}", field.DataType);
            System.Console.WriteLine("    DisplayedName     = {0}", field.DisplayedName);
            System.Console.WriteLine("    IsSupportsEditing = {0}", field.IsSupportsEditing);
            System.Console.WriteLine("    IsVisible         = {0}", field.IsVisible);
            System.Console.WriteLine("    Order             = {0}", field.Order);
        }
    }
    
    /// <summary>
    /// Prints the portfolio colors information.
    /// </summary>
    /// <param name="presentationColors">The presentation colors.</param>
    private static void PrintPortfolioColors(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfPresentationColors presentationColors)
    {
        System.Console.WriteLine("Colors:");
        System.Console.WriteLine(string.Format("  Background     = {0}", presentationColors.Background));
        System.Console.WriteLine(string.Format("  CardBackground = {0}", presentationColors.CardBackground));
        System.Console.WriteLine(string.Format("  CardBorder     = {0}", presentationColors.CardBorder));
        System.Console.WriteLine(string.Format("  PrimaryText    = {0}", presentationColors.PrimaryText));
        System.Console.WriteLine(string.Format("  SecondaryText  = {0}", presentationColors.SecondaryText));
    }
                    
    


    Here is an example that shows how to create new Portfolio:

    ' The project, which uses this code, must have references to the following assemblies:
    ' - Vintasoft.Imaging
    ' - Vintasoft.Imaging.Pdf
    
    ''' <summary>
    ''' Assemblies a portfolio from files and folders from specified path.
    ''' </summary>
    ''' <param name="rootPath">The root path to assembly portfolio.</param>
    ''' <param name="outputPdfFilename">The output PDF filename.</param>
    Public Shared Sub AssemblyPortfolio(rootPath As String, outputPdfFilename As String)
        ' create PDF document (version 1.7)
        Using document As New Vintasoft.Imaging.Pdf.PdfDocument(outputPdfFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17)
            ' add page to document
            Dim page As Vintasoft.Imaging.Pdf.Tree.PdfPage = document.Pages.Add(Vintasoft.Imaging.PaperSizeKind.A4)
    
            ' draw text on first page
            Using g As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = page.GetGraphics()
                Dim textBox As New Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure()
                textBox.Font = document.FontManager.GetStandardFont(Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman)
                textBox.FontSize = 30
                textBox.Location = New System.Drawing.PointF(0, 0)
                textBox.Size = page.MediaBox.Size
                textBox.TextAlignment = Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Top Or Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Left Or Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Right
                textBox.TextBrush = New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black)
                textBox.Text = "This document is Portfolio" & vbLf & "(Attachment Collection)" & vbLf & "To view Portfolio you should use PDF viewer compatible with PDF 1.7 ExtensionLevel 3."
                textBox.Draw(g)
            End Using
    
            ' create attachements
            document.CreateAttachments(True)
    
            ' set viewer settings
            document.Attachments.View = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionViewMode.TileMode
            document.Attachments.SplitterBar = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar(document)
            document.Attachments.SplitterBar.Direction = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSplitterBarDirection.None
            document.DocumentViewMode = Vintasoft.Imaging.Pdf.PdfDocumentViewMode.UseAttachments
    
            ' create field that defines sorting of files and folders in PDF viewer
            Dim sortFieldName As String = "Order"
            Dim sortField As New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(document, "Order (Sort)", Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Number)
            sortField.IsVisible = False
            document.Attachments.Schema = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema(document)
            document.Attachments.Schema.Add(sortFieldName, sortField)
    
            ' create sort properties
            document.Attachments.Sort = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort(document)
            document.Attachments.Sort.FieldNames = New String() {sortFieldName}
    
            ' use ZIP compression for files
            Dim filesCompression As Vintasoft.Imaging.Pdf.PdfCompression = Vintasoft.Imaging.Pdf.PdfCompression.Zip
    
            ' add files and folders to portfolio
            AddPathRecursively(document.Attachments.RootFolder, rootPath, False, filesCompression, True, sortFieldName)
    
            ' save changes in PDF document
            document.SaveChanges()
        End Using
    End Sub
    
    ''' <summary>
    ''' Adds the path (all files and sub folders) to specified portfolio folder.
    ''' </summary>
    ''' <param name="folder">The portfolio folder.</param>
    ''' <param name="path">The path that should be added to the portfolio.</param>
    ''' <param name="addPathAsFolder">Determines that portfolio must contain folder with the path filename.</param>
    ''' <param name="compression">The compression that should be applied to files and folders.</param>
    ''' <param name="generateThumbnails">Determines that portfolio must contain thumbnails for files.</param>
    ''' <param name="sortFieldName">Name of the sort field.</param>
    ''' <returns>
    ''' Added folder.
    ''' </returns>
    Private Shared Function AddPathRecursively(folder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder, path As String, addPathAsFolder As Boolean, compression As Vintasoft.Imaging.Pdf.PdfCompression, generateThumbnails As Boolean, sortFieldName As String) As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder
        ' sort order
        Dim order As Integer = 0
    
        ' folder to which path must be added
        Dim currentFolder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder
        ' if portfolio must contain folder with the path filename
        If addPathAsFolder Then
            ' add new folder to portfolio folder and use it as current folder
            currentFolder = folder.AddFolder(System.IO.Path.GetFileName(path))
            currentFolder.CreationDate = System.DateTime.Now
        Else
            ' use root folder as current folder
            currentFolder = folder
            folder.ModificationDate = System.DateTime.Now
        End If
    
        ' get directories in the specified path
        Dim paths As String() = System.IO.Directory.GetDirectories(path, "*", System.IO.SearchOption.TopDirectoryOnly)
        ' for each directory
        For Each subPath As String In paths
            ' if directory is hidden
            If (System.IO.File.GetAttributes(subPath) And System.IO.FileAttributes.Hidden) <> 0 Then
                ' ignore directory
                Continue For
            End If
    
            Try
                ' add the directory (all files and sub folders) to current portfolio folder
                Dim addedSubFolder As Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder = AddPathRecursively(currentFolder, subPath, True, compression, generateThumbnails, sortFieldName)
    
                ' if sorting must be used
                If sortFieldName IsNot Nothing Then
                    ' add data field collection to the portfolio folder
                    addedSubFolder.DataFields = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(folder.Document)
                    ' add data field value which defines sorting
                    addedSubFolder.DataFields.Add(sortFieldName, New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataField(folder.Document, order))
                    ' increment sort order
                    order += 1
                End If
            Catch ex As System.Exception
                System.Console.WriteLine(String.Format("{0}: {1}", currentFolder, ex.Message))
            End Try
        Next
    
        ' get files in the specified path
        Dim files As String() = System.IO.Directory.GetFiles(path, "*", System.IO.SearchOption.TopDirectoryOnly)
        ' if files are found
        If files.Length > 0 Then
            ' for each file
            For Each filename As String In files
                ' if file is hidden
                If (System.IO.File.GetAttributes(filename) And System.IO.FileAttributes.Hidden) <> 0 Then
                    ' ignore file
                    Continue For
                End If
    
                Try
                    ' add file
                    System.Console.WriteLine(String.Format("Add file {0}...", filename))
                    Dim file As Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification = currentFolder.AddFile(filename, compression)
                    file.EmbeddedFile.CreationDate = System.DateTime.Now
    
                    ' if thumbnail must be generated
                    If generateThumbnails Then
                        ' generate file thumbnail
                        file.Thumbnail = CreateThumbnailResource(file.Document, filename)
                    End If
    
                    ' if sorting must be used
                    If sortFieldName IsNot Nothing Then
                        ' add data field collection to the portfolio folder
                        file.DataFields = New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(folder.Document)
                        ' add data field value which defines sorting
                        file.DataFields.Add(sortFieldName, New Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataField(folder.Document, order))
                        ' increment sort order
                        order += 1
    
                    End If
                Catch ex As System.Exception
                    System.Console.WriteLine(String.Format("{0}: {1}", filename, ex.Message))
                End Try
            Next
            currentFolder.ModificationDate = System.DateTime.Now
        End If
    
        Return currentFolder
    End Function
    
    ''' <summary>
    ''' Creates PDF image resource with thumbnail of specified file.
    ''' </summary>
    ''' <param name="document">The PDF document.</param>
    ''' <param name="filename">The name of file for which thumbnail must be generated.</param>
    ''' <returns>Thumbnail image resource.</returns>
    Private Shared Function CreateThumbnailResource(document As Vintasoft.Imaging.Pdf.PdfDocument, filename As String) As Vintasoft.Imaging.Pdf.Tree.PdfImageResource
        ' get codec for file
        Dim codec As Vintasoft.Imaging.Codecs.Codec = Vintasoft.Imaging.Codecs.AvailableCodecs.GetCodecByExtension(System.IO.Path.GetExtension(filename))
        ' if code is available and codec has decoder
        If codec IsNot Nothing AndAlso codec.CanCreateDecoder Then
            Try
                ' get an image of first page of file
                Using image As New Vintasoft.Imaging.VintasoftImage(filename)
                    ' get image thumbnail
                    Using thumbnailImage As Vintasoft.Imaging.VintasoftImage = image.Thumbnail.GetThumbnailImage(100, 100)
                        Dim compressionSettings As New Vintasoft.Imaging.Pdf.PdfCompressionSettings()
                        compressionSettings.JpegQuality = 90
                        ' return PDF image-resource that contains image thumbnail
                        Return New Vintasoft.Imaging.Pdf.Tree.PdfImageResource(document, thumbnailImage, Vintasoft.Imaging.Pdf.PdfCompression.Jpeg, compressionSettings)
                    End Using
                End Using
            Catch
            End Try
        End If
        Return Nothing
    End Function
    
                  
    
    // The project, which uses this code, must have references to the following assemblies:
    // - Vintasoft.Imaging
    // - Vintasoft.Imaging.Pdf
    
    /// <summary>
    /// Assemblies a portfolio from files and folders from specified path.
    /// </summary>
    /// <param name="rootPath">The root path to assembly portfolio.</param>
    /// <param name="outputPdfFilename">The output PDF filename.</param>
    public static void AssemblyPortfolio(string rootPath, string outputPdfFilename)
    {
        // create PDF document (version 1.7)
        using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(
            outputPdfFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17))
        {
            // add page to document
            Vintasoft.Imaging.Pdf.Tree.PdfPage page = document.Pages.Add(
                Vintasoft.Imaging.PaperSizeKind.A4);
    
            // draw text on first page
            using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics g = page.GetGraphics())
            {
                Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure textBox =
                    new Vintasoft.Imaging.Pdf.Drawing.GraphicsFigures.TextBoxFigure();
                textBox.Font = document.FontManager.GetStandardFont(Vintasoft.Imaging.Pdf.Tree.Fonts.PdfStandardFontType.TimesRoman);
                textBox.FontSize = 30;
                textBox.Location = new System.Drawing.PointF(0, 0);
                textBox.Size = page.MediaBox.Size;
                textBox.TextAlignment =
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Top |
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Left |
                    Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Right;
                textBox.TextBrush = new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(System.Drawing.Color.Black);
                textBox.Text = "This document is Portfolio\n(Attachment Collection)\nTo view Portfolio you should use PDF viewer compatible with PDF 1.7 ExtensionLevel 3.";
                textBox.Draw(g);
            }
    
            // create attachements
            document.CreateAttachments(true);
    
            // set viewer settings
            document.Attachments.View = Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionViewMode.TileMode;
            document.Attachments.SplitterBar =
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSplitterBar(document);
            document.Attachments.SplitterBar.Direction =
                Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSplitterBarDirection.None;
            document.DocumentViewMode = Vintasoft.Imaging.Pdf.PdfDocumentViewMode.UseAttachments;
    
            // create field that defines sorting of files and folders in PDF viewer
            string sortFieldName = "Order";
            Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField sortField =
                new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchemaField(
                    document, "Order (Sort)",
                    Vintasoft.Imaging.Pdf.Tree.FileAttachments.AttachmentCollectionSchemaFieldDataType.Number);
            sortField.IsVisible = false;
            document.Attachments.Schema = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSchema(document);
            document.Attachments.Schema.Add(sortFieldName, sortField);
    
            // create sort properties
            document.Attachments.Sort = new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentCollectionSort(document);
            document.Attachments.Sort.FieldNames = new string[] { sortFieldName };
    
            // use ZIP compression for files
            Vintasoft.Imaging.Pdf.PdfCompression filesCompression = Vintasoft.Imaging.Pdf.PdfCompression.Zip;
    
            // add files and folders to portfolio
            AddPathRecursively(
                document.Attachments.RootFolder,
                rootPath,
                false,
                filesCompression,
                true,
                sortFieldName);
    
            // save changes in PDF document
            document.SaveChanges();
        }
    }
    
    /// <summary>
    /// Adds the path (all files and sub folders) to specified portfolio folder.
    /// </summary>
    /// <param name="folder">The portfolio folder.</param>
    /// <param name="path">The path that should be added to the portfolio.</param>
    /// <param name="addPathAsFolder">Determines that portfolio must contain folder with the path filename.</param>
    /// <param name="compression">The compression that should be applied to files and folders.</param>
    /// <param name="generateThumbnails">Determines that portfolio must contain thumbnails for files.</param>
    /// <param name="sortFieldName">Name of the sort field.</param>
    /// <returns>
    /// Added folder.
    /// </returns>
    private static Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder AddPathRecursively(
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder folder,
        string path,
        bool addPathAsFolder,
        Vintasoft.Imaging.Pdf.PdfCompression compression,
        bool generateThumbnails,
        string sortFieldName)
    {
        // sort order
        int order = 0;
    
        // folder to which path must be added
        Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder currentFolder;
        // if portfolio must contain folder with the path filename
        if (addPathAsFolder)
        {
            // add new folder to portfolio folder and use it as current folder
            currentFolder = folder.AddFolder(System.IO.Path.GetFileName(path));
            currentFolder.CreationDate = System.DateTime.Now;
        }
        else
        {
            // use root folder as current folder
            currentFolder = folder;
            folder.ModificationDate = System.DateTime.Now;
        }
    
        // get directories in the specified path
        string[] paths = System.IO.Directory.GetDirectories(path, "*", System.IO.SearchOption.TopDirectoryOnly);
        // for each directory
        foreach (string subPath in paths)
        {
            // if directory is hidden
            if ((System.IO.File.GetAttributes(subPath) & System.IO.FileAttributes.Hidden) != 0)
                // ignore directory
                continue;
    
            try
            {
                // add the directory (all files and sub folders) to current portfolio folder
                Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentFolder addedSubFolder =
                    AddPathRecursively(currentFolder, subPath, true, compression, generateThumbnails, sortFieldName);
    
                // if sorting must be used
                if (sortFieldName != null)
                {
                    // add data field collection to the portfolio folder
                    addedSubFolder.DataFields =
                        new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(folder.Document);
                    // add data field value which defines sorting
                    addedSubFolder.DataFields.Add(sortFieldName,
                        new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataField(folder.Document, order));
                    // increment sort order
                    order++;
                }
            }
            catch (System.Exception ex)
            {
                System.Console.WriteLine(string.Format("{0}: {1}", currentFolder, ex.Message));
            }
        }
    
        // get files in the specified path
        string[] files = System.IO.Directory.GetFiles(path, "*", System.IO.SearchOption.TopDirectoryOnly);
        // if files are found
        if (files.Length > 0)
        {
            // for each file
            foreach (string filename in files)
            {
                // if file is hidden
                if ((System.IO.File.GetAttributes(filename) & System.IO.FileAttributes.Hidden) != 0)
                    // ignore file
                    continue;
    
                try
                {
                    // add file
                    System.Console.WriteLine(string.Format("Add file {0}...", filename));
                    Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification file = currentFolder.AddFile(filename, compression);
                    file.EmbeddedFile.CreationDate = System.DateTime.Now;
    
                    // if thumbnail must be generated
                    if (generateThumbnails)
                        // generate file thumbnail
                        file.Thumbnail = CreateThumbnailResource(file.Document, filename);
    
                    // if sorting must be used
                    if (sortFieldName != null)
                    {
                        // add data field collection to the portfolio folder
                        file.DataFields =
                            new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataFieldCollection(folder.Document);
                        // add data field value which defines sorting
                        file.DataFields.Add(sortFieldName,
                            new Vintasoft.Imaging.Pdf.Tree.FileAttachments.PdfAttachmentDataField(folder.Document, order));
                        // increment sort order
                        order++;
                    }
    
                }
                catch (System.Exception ex)
                {
                    System.Console.WriteLine(string.Format("{0}: {1}", filename, ex.Message));
                }
            }
            currentFolder.ModificationDate = System.DateTime.Now;
        }
    
        return currentFolder;
    }
    
    /// <summary>
    /// Creates PDF image resource with thumbnail of specified file.
    /// </summary>
    /// <param name="document">The PDF document.</param>
    /// <param name="filename">The name of file for which thumbnail must be generated.</param>
    /// <returns>Thumbnail image resource.</returns>
    private static Vintasoft.Imaging.Pdf.Tree.PdfImageResource CreateThumbnailResource(
        Vintasoft.Imaging.Pdf.PdfDocument document, string filename)
    {
        // get codec for file
        Vintasoft.Imaging.Codecs.Codec codec = Vintasoft.Imaging.Codecs.AvailableCodecs.GetCodecByExtension(
            System.IO.Path.GetExtension(filename));
        // if code is available and codec has decoder
        if (codec != null && codec.CanCreateDecoder)
        {
            try
            {
                // get an image of first page of file
                using (Vintasoft.Imaging.VintasoftImage image = new Vintasoft.Imaging.VintasoftImage(filename))
                {
                    // get image thumbnail
                    using (Vintasoft.Imaging.VintasoftImage thumbnailImage = image.Thumbnail.GetThumbnailImage(100, 100))
                    {
                        Vintasoft.Imaging.Pdf.PdfCompressionSettings compressionSettings =
                            new Vintasoft.Imaging.Pdf.PdfCompressionSettings();
                        compressionSettings.JpegQuality = 90;
                        // return PDF image-resource that contains image thumbnail
                        return new Vintasoft.Imaging.Pdf.Tree.PdfImageResource(document, thumbnailImage,
                            Vintasoft.Imaging.Pdf.PdfCompression.Jpeg, compressionSettings);
                    }
                }
            }
            catch
            {
            }
        }
        return null;
    }
    
                    
    



    PdfEditorDemo/WpfPdfEditorDemo application.

    The demo application PdfEditorDemo/WpfPdfEditorDemo includes code, which allows to view, change, create an attachment collection of PDF document.