Creating a .NET MAUI Smart PDF Viewer App with Auto-Summary Generation Using OpenAI’s ChatGPT
Tags: dotnetmaui, openai, mobile, chatgpt
Published: 2023-09-22 14:25:53

---
title: Creating a .NET MAUI Smart PDF Viewer App with Auto-Summary Generation Using OpenAI’s ChatGPT
published: true
date: 2023-09-20 11:29:48 UTC
tags: dotnetmaui, openai, mobile, chatgpt
canonical_url: https://www.syncfusion.com/blogs/post/dotnet-maui-smart-pdf-viewer-using-openai.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7c791vx21mkrwsr7zvpm.png
---
Managing and digesting vast amounts of information efficiently is crucial in today’s fast-paced world. In the context of PDF documents, especially lengthy reports, research papers, or technical documentation, reading the entire document to grasp the main points can be time-consuming. That is where a smart PDF viewer app comes in handy.

This blog will explore how to develop a cross-platform smart PDF viewer app using Syncfusion [.NET MAUI](https://www.syncfusion.com/maui-controls ".NET MAUI controls") controls. Our app will enable users to load and view PDF files seamlessly, and it will provide an incredible time-saving feature: automatic summarization of the loaded documents.

To achieve this summary generation functionality, we will leverage the power of [OpenAI’s ChatGPT](https://openai.com/ "OpenAI's ChatGPT"), a cutting-edge natural language processing model. By integrating ChatGPT into our app, we can extract key information and generate concise summaries of PDF documents. This enables users to easily understand a document’s main points without having to read all the content.

The benefits of having a summary of a PDF file upfront are many. Users can save valuable time by quickly assessing the document’s relevance and importance, determining whether it warrants further investment in reading the complete text. Additionally, summaries aid in organizing and categorizing documents, enabling users to manage their digital libraries efficiently.

So, let us dive into the world of .NET MAUI and OpenAI’s ChatGPT to create a smart PDF viewer app that will revolutionize how we interact with and consume PDF documents. Get ready to save time, increase productivity, and unlock the power of intelligent document summarization!
## How to get an OpenAPI key

Follow these steps to obtain an OpenAI API key:

1. **Sign in to your OpenAI account** : Visit the [OpenAI website](https://www.openai.com/ "OpenAI website") and sign in using your account credentials.
2. **Navigate to the API section** : Once logged in, navigate to the API section of the OpenAI platform. This can usually be found in the account settings or developer dashboard.
3. **Create a new API key** : Look for an option to create a new secret API key. Click on it to initiate the key generation process. You will need to complete the purchase process, too.

## Create a .NET MAUI app with ChatGPT

Create a [.NET MAUI app](https://learn.microsoft.com/en-us/dotnet/maui/get-started/first-app?pivots=devices-windows&tabs=vswin "Building your first app with .NET MAUI") and follow the instructions within the project.

### Configuring ChatGPT APIs

After creating the .NET MAUI app, we need to integrate the ChatGPT library and call the ChatGPT APIs in our project. To do so, follow these steps:

1.**Add the** [**ChatGptNet library**](https://github.com/marcominerva/ChatGptNet "ChatGptNet library GitHub demo"): Start by referencing and bootstrapping the ChatGptNet library, which provides a convenient interface for interacting with the [OpenAI API](https://auth0.openai.com/u/login/identifier?state=hKFo2SA2VlY4cC0zYkx2Vl9JZUtnYXpzcE9MRXJPcEdEa0wzbqFur3VuaXZlcnNhbC1sb2dpbqN0aWTZIFFlcmxRcFVXN0pCNi1qNDI3Yk54OS1UbmQ0X3hpakVRo2NpZNkgRFJpdnNubTJNdTQyVDNLT3BxZHR3QjNOWXZpSFl6d0Q "OpenAI API") in .NET. Open the **Package Manager Console** from the **Tools** menu in [Visual Studio](https://visualstudio.microsoft.com/ "Visual Studio") and run the following command to install the ChatGptNet library:
```
Install-Package ChatGptNet
```

2.**Configure the ChatGptNet library** : In the [MauiP](https://github.com/CommunityToolkit/Maui/blob/main/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs "Community Toolkit .NET MAUI GitHub demo")[rogram.cs](https://github.com/CommunityToolkit/Maui/blob/main/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs "Community Toolkit .NET MAUI GitHub demo") file, locate the **CreateMauiApp** method and add the following code:
```csharp
builder.Services.AddChatGpt(options =>
{
    options.ApiKey = ""; // Your API key here;
    options.Organization = null; // Optional
    options.DefaultModel = ChatGptModels.Gpt35Turbo; // Default: ChatGptModels.Gpt35Turbo
    options.MessageLimit = 10; // Default: 10
    options.MessageExpiration = TimeSpan.FromMinutes(5); // Default: 1 hour
});
```

We’ve created a .NET MAUI app and configured the ChatGPT APIs in it.

## Key controls involved in the smart PDF viewer app

Building our smart PDF Viewer app involves leveraging the power of the Syncfusion [PDF Library](https://www.syncfusion.com/document-processing/pdf-framework/net/pdf-library ".NET PDF Library") and the following three .NET MAUI controls:

- [PDF Viewer](https://www.syncfusion.com/maui-controls/maui-pdf-viewer ".NET MAUI PDF Viewer")
- [Popup](https://www.syncfusion.com/maui-controls/maui-popup ".NET MAUI Popup")
- [Busy Indicator](https://www.syncfusion.com/maui-controls/maui-busy-indicator ".NET MAUI Busy Indicator Control")

These controls play vital roles in different aspects of our app, ensuring a seamless and user-friendly experience.

The [.NET MAUI PDF Viewer](https://www.syncfusion.com/maui-controls/maui-pdf-viewer ".NET MAUI PDF Viewer") takes center stage, enabling us to load and view PDF files within our app. With its rich features, the PDF Viewer provides a smooth and intuitive interface for navigating PDF documents. Users can zoom in and out, scroll through pages, and interact with the document content seamlessly. This control is the foundation of our PDF viewing functionality.

To enhance the user experience and provide quick access to document summaries, we incorporate the [.NET MAUI Popup control](https://www.syncfusion.com/maui-controls/maui-popup ".NET MAUI Popup"). When a user wants an overview of a loaded PDF file, the Popup control allows us to display the summary content elegantly and non-intrusively. Presenting the summary as a popup will enable users to conveniently view the key information without disrupting their reading flow or navigating away from the main document view. The Popup control provides a polished and visually appealing way to present the summary, enhancing the overall aesthetics of our app.

Since our app relies on the power of OpenAI’s ChatGPT for summarizing PDF documents, providing a responsive and interactive user experience is crucial during the summary generation process. This is where the Syncfusion [Busy Indicator](https://www.syncfusion.com/maui-controls/maui-busy-indicator ".NET MAUI Busy Indicator Control") comes into play. While the app communicates with the OpenAI API to generate the summary, the Busy Indicator ensures that users know the process is ongoing. It displays a visually engaging, animated indicator, explaining that the app is working behind the scenes. The Busy Indicator adds a touch of professionalism and reassures users that the app is actively processing their requests.

We’ll also leverage the power of the Syncfusion [PDF Library](https://www.syncfusion.com/document-processing/pdf-framework/net/pdf-library ".NET PDF Library") to extract the text from the PDF file. This library provides a comprehensive set of APIs and functionalities to work with PDF documents programmatically. We can extract the necessary content from the loaded PDF file, allowing OpenAI’s ChatGPT to analyze and generate the summary based on the extracted text. It can be seamlessly integrated with our app, enabling efficient text extraction and facilitating summary generation.

## Steps to create .NET MAUI smart PDF Viewer app with auto-summary generation powered by OpenAI’s ChatGPT

### Configuring the project

#### Step 1: Add the necessary NuGet packages

Add the [Syncfusion.Maui.Core](https://www.nuget.org/packages/Syncfusion.Maui.Core/ "Syncfusion.Maui.Core Nuget package"), [Syncfusion.Maui.PdfViewer](https://www.nuget.org/packages/Syncfusion.Maui.PdfViewer "Syncfusion.Maui.PdfViewer Nuget package"), and [Syncfusion.Maui.Popup](https://www.nuget.org/packages/Syncfusion.Maui.Popup "Syncfusion.Maui.Popup Nuget package") NuGet packages as references to your project from the [NuGet Gallery](https://www.nuget.org/ "Nuget Gallary").

#### Step 2: Register the handler

**Syncfusion.Maui.Core** is a dependent package for all Syncfusion .NET MAUI controls. In the **MauiProgram.cs** file, register the handler for Syncfusion core.

```csharp
using ChatGptNet;
using ChatGptNet.Models;
using ChatGptNet.ServiceConfigurations;
using Microsoft.Extensions.Logging;
using Syncfusion.Maui.Core.Hosting;

namespace SmartPDFViewer;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
	var builder = MauiApp.CreateBuilder();
	builder
	   .UseMauiApp<App>()
	   .ConfigureFonts(fonts =>
	   {
		fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
		fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
	   });

	   builder.ConfigureSyncfusionCore();

        builder.Services.AddChatGpt(options =>
        {

	    options.UseOpenAI("",null);
            options.DefaultModel = OpenAIChatGptModels.Gpt35Turbo; // Default: ChatGptModels.Gpt35Turbo
            options.MessageLimit = 10; // Default: 10
            options.MessageExpiration = TimeSpan.FromMinutes(5); // Default: 1 hour
        });

        builder.Logging.AddDebug();
		return builder.Build();
    }
}
```

#### Step 3: Adding resources

Add a new folder to the project named **Assets** and add the PDF document you need to display in the PDF Viewer. In this demonstration, a PDF file named **pdfexample.pdf** has been used. You can also use a file browser to choose files dynamically from the device.

### Process the PDF document with OpenAI APIs

Follow these steps to process the PDF document with OpenAI APIs:

#### Step 1: Class, interfaces, and property declarations

Refer to the following code example. In it, the code defines a class called **PdfViewerViewModel** that implements the [INotifyPropertyChanged](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=net-7.0 "INotifyPropertyChanged interface of .NET MAUI Framework") interface. This interface enables the class to notify subscribers when the value of a property changes.

```csharp
class PdfViewerViewModel : INotifyPropertyChanged
{
    private Stream? m_pdfDocumentStream;

    public event PropertyChangedEventHandler? PropertyChanged;

    private Guid _sessionGuid = Guid.Empty;

    public Stream PdfDocumentStream
    {
        get
        {
            return m_pdfDocumentStream;
        }
        set
        {
            m_pdfDocumentStream = value;
            OnPropertyChanged("PdfDocumentStream");
        }
    }

    private bool isBusy = false;

    public bool IsBusy
    {
        get
        {
            return isBusy;
        }
        set
        {
            isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    private String processedText = String.Empty;

    public String ProcessedText
    {
        get
        {
            return processedText;
        }
        set
        {
            processedText = value;
            OnPropertyChanged("ProcessedText");
        }
    }

    private int summaryIntensity = 50;

    public int SummaryIntensity
    {
        get
        {
            return summaryIntensity;
        }
        set
        {
            summaryIntensity = value;
            OnPropertyChanged("SummaryIntensity");
        }
    }

    public PdfViewerViewModel()
    {
        m_pdfDocumentStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("SmartPDFViewer.Assets.pdfexample.pdf");
    }

}
```

The class declares several properties, including:

- **PdfDocumentStream**: This represents a PDF document stream that will be loaded and displayed in the PDF Viewer.
- **IsBusy**: Indicates whether the app is currently busy operating.
- **ProcessedText**: Stores the processed text or summary generated from the PDF document.
- **SummaryIntensity**: This represents the intensity, or length, of the summary.

#### Step 2: Add the constructor

The **PdfViewerViewModel** class includes a constructor that initializes the **PdfDocumentStream** property with a PDF file stream obtained from the app’s assembly resources.

Refer to the following code example.

```csharp
class PdfViewerViewModel : INotifyPropertyChanged
{
    private Stream? m_pdfDocumentStream;

    public event PropertyChangedEventHandler? PropertyChanged;

    private Guid _sessionGuid = Guid.Empty;

    public Stream PdfDocumentStream
    {
        get
        {
            return m_pdfDocumentStream;
        }
        set
        {
            m_pdfDocumentStream = value;
            OnPropertyChanged("PdfDocumentStream");
        }
    }

    private bool isBusy = false;

    public bool IsBusy
    {
        get
        {
            return isBusy;
        }
        set
        {
            isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    private String processedText = String.Empty;

    public String ProcessedText
    {
        get
        {
            return processedText;
        }
        set
        {
            processedText = value;
            OnPropertyChanged("ProcessedText");
        }
    }

    private int summaryIntensity = 50;

    public int SummaryIntensity
    {
        get
        {
            return summaryIntensity;
        }
        set
        {
            summaryIntensity = value;
            OnPropertyChanged("SummaryIntensity");
        }
    }

    public PdfViewerViewModel()
    {
        m_pdfDocumentStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("SmartPDFViewer.Assets.pdfexample.pdf");
    }

}
```

#### Step 3: Add the OnPropertyChanged method

Refer to the following code example. In it, the **OnPropertyChanged** method is called to raise the **PropertyChanged** event. It is used to notify subscribers when the value of a specific property has changed.

```csharp
class PdfViewerViewModel : INotifyPropertyChanged
{
    private Stream? m_pdfDocumentStream;

    public event PropertyChangedEventHandler? PropertyChanged;

    private Guid _sessionGuid = Guid.Empty;

    public Stream PdfDocumentStream
    {
        get
        {
            return m_pdfDocumentStream;
        }
        set
        {
            m_pdfDocumentStream = value;
            OnPropertyChanged("PdfDocumentStream");
        }
    }

    private bool isBusy = false;

    public bool IsBusy
    {
        get
        {
            return isBusy;
        }
        set
        {
            isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    private String processedText = String.Empty;

    public String ProcessedText
    {
        get
        {
            return processedText;
        }
        set
        {
            processedText = value;
            OnPropertyChanged("ProcessedText");
        }
    }

    private int summaryIntensity = 50;

    public int SummaryIntensity
    {
        get
        {
            return summaryIntensity;
        }
        set
        {
            summaryIntensity = value;
            OnPropertyChanged("SummaryIntensity");
        }
    }

    public PdfViewerViewModel()
    {
        m_pdfDocumentStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("SmartPDFViewer.Assets.pdfexample.pdf");
    }

    public void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

}
```

#### Step 4: Implement the LoadFile method

In the following code example, the **LoadFile** method is used to load the PDF document and extract its text content. It uses Syncfusion’s [PdfLoadedDocument class](https://help.syncfusion.com/cr/file-formats/Syncfusion.Pdf.Parsing.PdfLoadedDocument.html "PdfLoadedDocument class of .NET MAUI PDF Viewer") to load the document, iterates through its pages, and extracts text using the **ExtractText** method. After that, the extracted text is stored in the **extractedText** variable.

Refer to the following code example.

```csharp
class PdfViewerViewModel : INotifyPropertyChanged
{
    private Stream? m_pdfDocumentStream;

    public event PropertyChangedEventHandler? PropertyChanged;

    private Guid _sessionGuid = Guid.Empty;

    public Stream PdfDocumentStream
    {
        get
        {
            return m_pdfDocumentStream;
        }
        set
        {
            m_pdfDocumentStream = value;
            OnPropertyChanged("PdfDocumentStream");
        }
    }

    private bool isBusy = false;

    public bool IsBusy
    {
        get
        {
            return isBusy;
        }
        set
        {
            isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    private String processedText = String.Empty;

    public String ProcessedText
    {
        get
        {
            return processedText;
        }
        set
        {
            processedText = value;
            OnPropertyChanged("ProcessedText");
        }
    }

    private int summaryIntensity = 50;

    public int SummaryIntensity
    {
        get
        {
            return summaryIntensity;
        }
        set
        {
            summaryIntensity = value;
            OnPropertyChanged("SummaryIntensity");
        }
    }

    public PdfViewerViewModel()
    {
        m_pdfDocumentStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("SmartPDFViewer.Assets.pdfexample.pdf");
    }

    public void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
    string extractedText = string.Empty;

    public void LoadFile()
    {
        PdfLoadedDocument loadedDocument = new PdfLoadedDocument(PdfDocumentStream);
        PdfLoadedPageCollection loadedPages = loadedDocument.Pages;
        TextLineCollection lineCollection = new TextLineCollection();
        foreach (PdfLoadedPage loadedPage in loadedPages)
        {
            extractedText += loadedPage.ExtractText(out lineCollection);
        }
        loadedDocument.Close(true);
    }

}
```

#### Step 5: Implement the GenerateSummary method

The **GenerateSummary** method is used to generate a summary of the PDF content using the ChatGPT API. If the PDF file is not loaded, it calls the **LoadFile** method. It then sets the **IsBusy** property to **true** to indicate that the app is performing the summary generation. It obtains a response from the ChatGPT API by invoking the **AskAsync** method and passing the session ID and a prompt with the extracted text. The generated summary is then assigned to the **ProcessedText** property. Finally, the GenerateSummary method sets the **IsBusy** property to **false** to indicate that the task is complete.

The **PdfViewerViewModel** class encapsulates the logic and properties required to load a PDF document, extract its text, and generate a summary using the ChatGPT API. It leverages event notifications and property changes to ensure proper communication and updates to the UI.

```csharp
class PdfViewerViewModel : INotifyPropertyChanged
{
    private Stream? m_pdfDocumentStream;

    public event PropertyChangedEventHandler? PropertyChanged;

    private Guid _sessionGuid = Guid.Empty;

    public Stream PdfDocumentStream
    {
        get
        {
            return m_pdfDocumentStream;
        }
        set
        {
            m_pdfDocumentStream = value;
            OnPropertyChanged("PdfDocumentStream");
        }
    }

    private bool isBusy = false;

    public bool IsBusy
    {
        get
        {
            return isBusy;
        }
        set
        {
            isBusy = value;
            OnPropertyChanged("IsBusy");
        }
    }

    private String processedText = String.Empty;

    public String ProcessedText
    {
        get
        {
            return processedText;
        }
        set
        {
            processedText = value;
            OnPropertyChanged("ProcessedText");
        }
    }

    private int summaryIntensity = 50;

    public int SummaryIntensity
    {
        get
        {
            return summaryIntensity;
        }
        set
        {
            summaryIntensity = value;
            OnPropertyChanged("SummaryIntensity");
        }
    }

    public PdfViewerViewModel()
    {
        m_pdfDocumentStream = typeof(App).GetTypeInfo().Assembly.GetManifestResourceStream("SmartPDFViewer.Assets.pdfexample.pdf");
    }

    public void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
    string extractedText = string.Empty;

    public void LoadFile()
    {
        PdfLoadedDocument loadedDocument = new PdfLoadedDocument(PdfDocumentStream);
        PdfLoadedPageCollection loadedPages = loadedDocument.Pages;
        TextLineCollection lineCollection = new TextLineCollection();
        foreach (PdfLoadedPage loadedPage in loadedPages)
        {
            extractedText += loadedPage.ExtractText(out lineCollection);
        }
        loadedDocument.Close(true);
    }

    internal async void GenerateSummary(IChatGptClient _chatGptClient, bool isFileLoaded = false)
    {
        if (!isFileLoaded)
        {
            LoadFile();
        }

        this.IsBusy = true;

        if (_sessionGuid == Guid.Empty)
        {
            _sessionGuid = Guid.NewGuid();
        }
        ChatGptResponse response = await _chatGptClient.AskAsync(_sessionGuid,
        "Please provide a summary("+ this.SummaryIntensity +" words) of the content in the PDF file below :" + extractedText);

        this.ProcessedText = response.GetMessage(); ;
        this.IsBusy = false;
    }
}
```
## Implementing the UI design

Follow these steps to implement the UI design:

### Step 1: XAML namespace and resource declarations

The code begins with the declaration of XML namespaces used in the XAML file. These namespaces include several custom namespaces for the smart PDF Viewer app, Syncfusion controls, and converters.

- **xmlns:viewer=”clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer”** : The viewer namespace declaration references the Syncfusion PDF Viewer control. It provides access to the PDF viewing capabilities and features of the [Syncfusion.Maui.PdfViewer](https://www.nuget.org/packages/Syncfusion.Maui.PdfViewer "Syncfusion.Maui.PdfViewer NuGet package") assembly.
- **xmlns:core=”clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core”** : The core namespace declaration refers to the [Syncfusion.Maui.Core](https://www.nuget.org/packages/Syncfusion.Maui.Core/ "Syncfusion.Maui.Core NuGet package") assembly. It provides access to core Syncfusion controls and utilities used in the app, such as the [Busy Indicator control](https://help.syncfusion.com/maui/busy-indicator/overview "Getting started with .NET MAUI Busy Indicator").
- **xmlns:popup=”clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup”** : The popup namespace declaration points to the [Syncfusion.Maui.Popup](https://www.nuget.org/packages/Syncfusion.Maui.Popup "Syncfusion.Maui.Popup NuGet package") assembly. It enables the [Popup control](https://help.syncfusion.com/maui/popup/getting-started "Getting started with .NET MAUI Popup"), which displays the summary content in a popup window.
- **xmlns:syncfusionConverters=”clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core”** : The syncfusionConverters namespace declaration refers to the [Syncfusion.Maui.Core.Converters](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Core.Converters.html?tabs=tabid-1 "Syncfusion.Maui.Core.Converters Namespace") assembly. It provides access to the converter classes, such as [InvertedBoolConverter](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/converters/inverted-bool-converter "InvertedBoolConverter class of .NET MAUI Framework"), which is used in the XAML file to invert Boolean values for data-binding purposes.

Refer to the following code example. In it, within the **ContentPage**, the **Resources** section is defined to declare resources used within the XAML file. In this case, an instance of the [InvertedBoolConverter](https://learn.microsoft.com/en-us/dotnet/api/xamarin.communitytoolkit.converters.invertedboolconverter?view=xamarin-community-toolkit-sdk "InvertedBoolConverter class of .NET MAUI Framework") class from the [Syncfusion.Maui.Core.Converters](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Core.Converters.html?tabs=tabid-1 "Syncfusion.Maui.Core.Converters Namespace") namespace is created and assigned a key.

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SmartPDFViewer"
             xmlns:viewer="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer"
             xmlns:core="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
             xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
             xmlns:syncfusionConverters="clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core"
             x:Class="SmartPDFViewer.MainPage">
 <ContentPage.Resources>
  <syncfusionConverters:InvertedBoolConverter x:Key="invertedBoolConverter"/>
 </ContentPage.Resources>
</ContentPage>
```

### Step 2: Add a Grid layout

Inside the **ContentPage**, let’s define a **Grid** element. The **Grid** layout allows arranging elements in rows and columns. It serves as the container for other controls in the XAML file.

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SmartPDFViewer"
             xmlns:viewer="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer"
             xmlns:core="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
             xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
             xmlns:syncfusionConverters="clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core"
             x:Class="SmartPDFViewer.MainPage">
 <ContentPage.Resources>
  <syncfusionConverters:InvertedBoolConverter x:Key="invertedBoolConverter"/>
 </ContentPage.Resources>
 <Grid>
 </Grid>
</ContentPage>
```

### Step 3: Add the PDF Viewer control

Within the **Grid** , add the [SfPdfViewer](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.PdfViewer.SfPdfViewer.html "SfPdfViewer class of .NET MAUI") control from [Syncfusion.Maui.PdfViewer](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.PdfViewer.html "Syncfusion.Maui.PdfViewer Namespace") namespace. This control is responsible for loading and displaying the PDF document. Then, bind the [DocumentSource](https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.xml.documentsource?view=netframework-4.8.1 "Xml.DocumentSource property") property to the **PdfDocumentStream** property, which determines the source of the PDF document to be displayed.

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SmartPDFViewer"
             xmlns:viewer="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer"
             xmlns:core="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
             xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
             xmlns:syncfusionConverters="clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core"
             x:Class="SmartPDFViewer.MainPage">
 <ContentPage.Resources>
  <syncfusionConverters:InvertedBoolConverter x:Key="invertedBoolConverter"/>
 </ContentPage.Resources>
 <Grid>
  <viewer:SfPdfViewer DocumentSource="{Binding PdfDocumentStream}">
  </viewer:SfPdfViewer>
 </Grid>
</ContentPage>
```

### Step 4: Designing the summary button and popup

Next, add an **Image** control to serve as a button for displaying the summary. It is accompanied by a [TapGestureRecognizer](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/gestures/tap "Recognizing Tap Gestures in .NET MAUI") to handle the tap event. When the button is tapped, the [SfPopup](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Popup.SfPopup.html "SfPopup Class of .NETMAUI") control will be invoked to show the summary content as a popup. It includes a **ContentTemplate** that defines the layout of the popup, including a [SfBusyIndicator](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Core.SfBusyIndicator.html?tabs=tabid-1 "SfBusyIndicator class of .NET MAUI") to display a loading animation while the summary is being processed. The summary text is displayed in a **Label** within a **ScrollView**.

Refer to the following code example.

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SmartPDFViewer"
             xmlns:viewer="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer"
             xmlns:core="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
             xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
             xmlns:syncfusionConverters="clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core"
             x:Class="SmartPDFViewer.MainPage">
 <ContentPage.Resources>
  <syncfusionConverters:InvertedBoolConverter x:Key="invertedBoolConverter"/>
 </ContentPage.Resources>
 <Grid>
  <viewer:SfPdfViewer DocumentSource="{Binding PdfDocumentStream}">
  </viewer:SfPdfViewer>
   <Image Source="summary.png" WidthRequest="50" HeightRequest="50" Margin="50" HorizontalOptions="End" VerticalOptions="End">
    <Image.GestureRecognizers>
     <TapGestureRecognizer Tapped="ShowSummary_Tapped"/>
    </Image.GestureRecognizers>
   </Image>
   <popup:SfPopup x:Name="popupDisplay" ShowHeader="True" HeaderHeight="50" HeightRequest="500" WidthRequest="400">
   </popup:SfPopup>
 </Grid>
</ContentPage>
```

### Step 5: Designing the summary header and controls

The [SfPopup](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.Popup.SfPopup.html "SfPopup class of .NET MAUI") control also includes a **HeaderTemplate** that defines the layout of the header section. In this case, we’ll display a **Label** with the text “Summary.”

Following the summary content is a second **Grid** element containing controls related to the summary. It includes a **Label** , a **Slider** , and an **Image**. These controls allow users to adjust the summary intensity, refresh the summary, and control the visibility of the Busy Indicator.

Refer to the following code example.

```xml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SmartPDFViewer"
             xmlns:viewer="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer"
             xmlns:core="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
             xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"
             xmlns:syncfusionConverters="clr-namespace:Syncfusion.Maui.Core.Converters;assembly=Syncfusion.Maui.Core"
             x:Class="SmartPDFViewer.MainPage">
 <ContentPage.Resources>
  <syncfusionConverters:InvertedBoolConverter x:Key="invertedBoolConverter"/>
 </ContentPage.Resources>
 <Grid>
  <viewer:SfPdfViewer DocumentSource="{Binding PdfDocumentStream}">
  </viewer:SfPdfViewer>
   <Image Source="summary.png" WidthRequest="50" HeightRequest="50" Margin="50" HorizontalOptions="End" VerticalOptions="End">
    <Image.GestureRecognizers>
     <TapGestureRecognizer Tapped="ShowSummary_Tapped"/>
    </Image.GestureRecognizers>
   </Image>
   <popup:SfPopup x:Name="popupDisplay" ShowHeader="True" HeaderHeight="50" HeightRequest="500" WidthRequest="400">
    <popup:SfPopup.ContentTemplate>
     <DataTemplate>
      <Grid RowDefinitions="*,50">
       <core:SfBusyIndicator IsRunning="{Binding IsBusy}" OverlayFill="#FFFFFF">
        <Grid Background="White" Padding="5">
         <ScrollView>
          <Label Text="{Binding ProcessedText}"/>
         </ScrollView>
        </Grid>
       </core:SfBusyIndicator>
       <Grid Grid.Row="1" ColumnDefinitions="*,40" IsVisible="{Binding IsBusy, Converter={StaticResource invertedBoolConverter}}">
        <Label VerticalOptions="Start" Margin="0,2" HorizontalOptions="Start" Text="Conciseness" FontSize="10" FontAttributes="Bold"/>
        <Slider Margin="0,10,10,5" VerticalOptions="Center" Value="{Binding SummaryIntensity, Mode=TwoWay}" Minimum="50" Maximum="500"/>
        <Image Source="refresh.png" WidthRequest="30" HeightRequest="30" Grid.Column="1">
         <Image.GestureRecognizers>
          <TapGestureRecognizer Tapped="RefreshSummary_Tapped"/>
         </Image.GestureRecognizers>
        </Image>
       </Grid>
      </Grid>
     </DataTemplate>
    </popup:SfPopup.ContentTemplate>
    <popup:SfPopup.HeaderTemplate>
     <DataTemplate>
      <Label Text="Summary" FontSize="14" FontAttributes="Bold" Margin="10,0,10,0"/>
     </DataTemplate>
    </popup:SfPopup.HeaderTemplate>
   </popup:SfPopup>
 </Grid>
</ContentPage>
```
### Implementing the code for the UI

Follow these steps to implement the code for the UI:

#### Step 1: Namespace and class declarations

Declare the [Syncfusion.Pdf.Parsing](https://help.syncfusion.com/cr/file-formats/Syncfusion.Pdf.Parsing.html "Syncfusion.Pdf.Parsing Namespace"), [Syncfusion.Pdf](https://help.syncfusion.com/cr/file-formats/Syncfusion.Pdf.html "Syncfusion.Pdf Namespace"), [System.ComponentModel](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel?view=net-7.0 "System.ComponentModel Namespace"), [System.Reflection](https://learn.microsoft.com/en-us/dotnet/api/system.reflection?view=net-7.0 "System.Reflection Namespace"), **ChatGptNet** , and **ChatGptNet.Models** namespaces. These namespaces provide access to the required classes and functionalities.

Then, declare a class named **MainPage** that extends the **ContentPage**. This class is used to represent the main page of the smart PDF Viewer app.

```csharp
using Syncfusion.Pdf.Parsing;
using Syncfusion.Pdf;
using System.ComponentModel;
using System.Reflection;
using ChatGptNet;
using ChatGptNet.Models;

namespace SmartPDFViewer;

public partial class MainPage : ContentPage
{
}
```

#### Step 2: Initialization and event handling

Initialize an instance of the **PdfViewerViewModel** class named **viewModel**. This view model manages the data and logic associated with the PDF Viewer.

Then, declare a private variable **\_chatGptClient** of type **IChatGptClient** to communicate with the ChatGPT API.

Define the constructor **MainPage()**, initialize the page’s components, and set the **BindingContext** property to the **viewModel** instance. Also, attach an event handler, **MainPage\_Loaded** , to the **Loaded** event of the page.

```csharp
public partial class MainPage : ContentPage
{

    PdfViewerViewModel viewModel = new PdfViewerViewModel();

    private IChatGptClient _chatGptClient;

    public MainPage()
    {
	InitializeComponent();
        this.BindingContext = viewModel;
        this.Loaded += MainPage_Loaded;
    }
}
```

#### Step 3: Hook the MainPage\_Loaded event handler

The **MainPage\_Loaded** event handler is called when the page is loaded. It retrieves the **IChatGptClient** instance from the **MauiContext** services and assigns it to the **\_chatGptClient** variable. This allows the page to access the ChatGPT API for generating summaries.

Refer to the following code example.

```csharp
public partial class MainPage : ContentPage
{

    PdfViewerViewModel viewModel = new PdfViewerViewModel();

    private IChatGptClient _chatGptClient;

    public MainPage()
    {
	InitializeComponent();
        this.BindingContext = viewModel;
        this.Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, EventArgs e)
    {
        _chatGptClient = Handler.MauiContext.Services.GetService<IChatGptClient>();
    }

}
```

#### Step 4: Hook the ShowSummary\_Tapped event handler

The **ShowSummary\_Tapped** event handler is called when the user taps on an element, triggering the display of the summary. It shows the popup display by calling the **Show** method on the **popupDisplay** instance. After that, it invokes the **GenerateSummary** method on the **viewModel** instance, passing the **\_chatGptClient** as an argument. This triggers the generation of a summary using the ChatGPT API.

Refer to the following code example.

```csharp
public partial class MainPage : ContentPage
{

    PdfViewerViewModel viewModel = new PdfViewerViewModel();

    private IChatGptClient _chatGptClient;

    public MainPage()
    {
	InitializeComponent();
        this.BindingContext = viewModel;
        this.Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, EventArgs e)
    {
        _chatGptClient = Handler.MauiContext.Services.GetService<IChatGptClient>();
    }

    private void ShowSummary_Tapped(object sender, TappedEventArgs e)
    {
        this.popupDisplay.Show();
        viewModel.GenerateSummary(_chatGptClient);
    }
}
```

### Step 5: Hook the RefreshSummary\_Tapped event handler

The **RefreshSummary\_Tapped** event handler is called when the user taps an element to refresh the summary. It directly invokes the **GenerateSummary** method on the **viewModel** instance, passing the **\_chatGptClient** and **true** as arguments. The second argument indicates that the file is already loaded, and a new summary should be generated.

Refer to the following code example.

```csharp
public partial class MainPage : ContentPage
{

    PdfViewerViewModel viewModel = new PdfViewerViewModel();

    private IChatGptClient _chatGptClient;

    public MainPage()
    {
	InitializeComponent();
        this.BindingContext = viewModel;
        this.Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, EventArgs e)
    {
        _chatGptClient = Handler.MauiContext.Services.GetService<IChatGptClient>();
    }

    private void ShowSummary_Tapped(object sender, TappedEventArgs e)
    {
        this.popupDisplay.Show();
        viewModel.GenerateSummary(_chatGptClient);
    }

    private void RefreshSummary_Tapped(object sender, TappedEventArgs e)
    {
        viewModel.GenerateSummary(_chatGptClient, true);
    }
}
```

All the code provided in this blog sets up the main page of the smart PDF Viewer app, initializes the necessary components, handles events for displaying and refreshing the summary, and connects with the ChatGPT API for generating the summaries. If you follow along, you will have a fully functional app that allows seamless PDF viewing and provides invaluable document summaries at your fingertips.

Refer to the following output GIF image to see the smart PDF Viewer app in action.

![.NET MAUI Smart PDF Viewer App with Auto-Summary Generation Using OpenAI’s ChatGPT](https://www.syncfusion.com/blogs/wp-content/uploads/2023/09/NET-MAUI-Smart-PDF-Viewer-App-with-Auto-Summary-Generation-Using-OpenAIs-ChatGPT.gif)
_.NET MAUI Smart PDF Viewer App with Auto-Summary Generation Using OpenAI’s ChatGPT_
## GitHub reference
Also, check out the [.NET MAUI Smart PDF Viewer using OpenAI’s ChatGPT GitHub demo.](https://github.com/SyncfusionExamples/maui-general-samples/tree/main/SmartPDFViewer)

## Conclusion

Thanks for reading! In this blog, we’ve seen how to create a smart PDF Viewer app using Syncfusion [.NET MAUI](https://www.syncfusion.com/maui-controls ".NET MAUI controls") controls and [OpenAI’s ChatGPT](https://openai.com/ "OpenAI's ChatGPT") API. The app generates summaries for loaded PDFs and gives users the ability to experiment with different ChatGPT models for improved results. By combining the OpenAI ChatGPT API with Syncfusion’s controls, developers can create sophisticated and user-friendly PDF viewing experiences.

Syncfusion’s [.NET MAUI](https://www.syncfusion.com/maui-controls ".NET MAUI controls") controls provide developers with a wide range of tools for building powerful and feature-rich apps. They offer extensive customization options and easy-to-use APIs, allowing seamless integration with the .NET MAUI framework. As a result, developers can easily create cross-platform apps with enhanced functionality using Syncfusion’s controls.

Existing customers can access the latest version of Essential Studio from the [License and Downloads](https://www.syncfusion.com/account/downloads "Essential Studio License and Downloads page") page. Developers who are new to Syncfusion can explore Essential Studio’s features with a 30-day [free trial](https://www.syncfusion.com/downloads "Get the free evaluation of the Essential Studio products").

You can also contact us through our [support forums](https://www.syncfusion.com/forums "Syncfusion Support Forum"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). We are always happy to assist you.

**Disclaimer: ** You will need to use professional skill and judgment when doing any implementation. This provides only a sample. Syncfusion is not affiliated with ChatGPT and is not responsible for any results.

## Related blogs

- [Introducing the 9th Set of New .NET MAUI Controls and Features](https://www.syncfusion.com/blogs/post/whats-new-dotnet-maui-2.aspx "Blog: Introducing the 9th Set of New .NET MAUI Controls and Features")
- [What’s New in 2023 Volume 3: .NET MAUI Charts](https://www.syncfusion.com/blogs/post/whats-new-dotnet-maui-chart.aspx "Blog: What’s New in 2023 Volume 3: .NET MAUI Charts")
- [The Ultimate Patient Appointment Manager App in .NET MAUI](https://www.syncfusion.com/blogs/post/patient-appointment-app-dotnet-maui.aspx "Blog: The Ultimate Patient Appointment Manager App in .NET MAUI")
- [Mastering Globalization: Utilizing Calendar Types in .NET MAUI Calendar Control](https://www.syncfusion.com/blogs/post/globalization-in-dotnet-maui-calendar.aspx "Blog: Mastering Globalization: Utilizing Calendar Types in .NET MAUI Calendar Control")
- [Easily Build ChatGPT-like App in .NET MAUI using OpenAI APIs](https://www.syncfusion.com/blogs/post/dotnet-maui-chatgpt-like-app-using-openai.aspx "Blog: Easily Build ChatGPT-like App in .NET MAUI using OpenAI APIs")