ComponentOne Document Library for UWP
Text Search
PdfDocumentSource for UWP > Features > Text Search

PDFDocumentSource allows you to implement text search in a PDF file by matching the search criteria and examining all the words stored in the file through C1TextSearchManager class, member of C1.Xaml.Document namespace. The class provides various methods, such as FindStart to find the first occurrence, FindNext to find the next occurrence, and FindPrevious to find the previous occurrence of the searched text. You can use C1FindTextParams(string text, bool wholeWord, bool matchCase) method to initialize a new instance of C1FindTextParams class with the following parameters:

The following image shows the word searched in a PDF file and the list of matches as search results.

To search text programmatically

In this sample code, we use the FindStart method on the C1TextSearchManager to find instances of the search text.

Step 1: Setting up the application

  1. Add C1PdfDocumentSource, OpenFileDialog, ListView, two TextBox, and three Button controls to the Form.
  2. Add columns to the ListView control by adding the following XAML code.
    XAML
    Copy Code
    <ListView x:Name="listView1" HorizontalAlignment="Left" Width="585" Margin="10,150,0,10">
        <ListView.HeaderTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="#" Margin="5,5,0,0"></TextBlock>
                    <TextBlock Text="Page" Margin="15,5,0,0"></TextBlock>
                    <TextBlock Text="Bounds" Margin="40,5,0,0"></TextBlock>
                    <TextBlock Text="Position" Margin="40,5,0,0"></TextBlock>
                    <TextBlock Text="NearText" Margin="40,5,0,0"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.HeaderTemplate>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding ID}" Margin="5,0,0,0"></TextBlock>
                    <TextBlock Text="{Binding Page}" Margin="15,0,0,0"></TextBlock>
                    <TextBlock Text="{Binding Bounds}" Margin="30,5,0,0"></TextBlock>
                    <TextBlock Text="{Binding Position}" Margin="30,5,0,0"></TextBlock>
                    <TextBlock Text="{Binding NearText}" Margin="30,5,0,0"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

Step 2: Browse and search text in a PDF file

  1. Switch to the code view and add the following namespace.
    Imports C1.Xaml.Document
    
    using C1.Xaml.Document;
    
  2. Add a PDF file to the project. In our case, we have used PDF file named DefaultDocument.pdf from the product sample.
  3. Add the following code to create an instance of C1TextSearchManager and StorageFile class, initialize the instance of C1PDFDocumentSource, and declare a variable, loadedFile, of string type.
    ' C1TextSearchManager instance used by the search.
    Private tsm As C1TextSearchManager
    
    ' File name of the currently loaded document.
    Private loadedFile As String = Nothing
    
    Private pds As New C1PdfDocumentSource()
    Private file As StorageFile
    
    // C1TextSearchManager instance used by the search.
    C1TextSearchManager tsm;
    
    // File name of the currently loaded document.
    private string loadedFile = null;
    
    C1PdfDocumentSource pds = new C1PdfDocumentSource();
    StorageFile file;
    
  4. Add the following code below the InitializeComponent() method.
    ' Create and initialize the C1TextSearchManager:
    tsm = New C1TextSearchManager(pds)
    tsm.FoundPositionsChanged += Tsm_FoundPositionsChanged
    
    'UseSystemRendering is set to false to allow 
    'text search using built-in PDF renderer
    pds.UseSystemRendering = False
    
    // Create and initialize the C1TextSearchManager:
    tsm = new C1TextSearchManager(pds);
    tsm.FoundPositionsChanged += Tsm_FoundPositionsChanged;
    
    //UseSystemRendering is set to false to allow 
    //text search using built-in PDF renderer
    pds.UseSystemRendering = false;
    
  5. Add the following code to directly access the PDF file in the app package.
    'use ms-aapx protocol to access PDF file in the app package
    file = Await StorageFile.GetFileFromApplicationUriAsync(New Uri _
           ("ms-appx:///DefaultDocument.pdf"))
    
    ' Use sample file:
    tbFile.Text = Path.GetFullPath(file.Name)
    
    //use ms-aapx protocol to access PDF file in the app package
    file = await StorageFile.GetFileFromApplicationUriAsync(new
           Uri("ms-appx:///DefaultDocument.pdf"));
    
    // Use sample file:
    tbFile.Text = Path.GetFullPath(file.Name);
    
  6. Add the following code to the click event of btnFile to open the dialog box for browsing and opening a PDF file.
    Private Sub btnFile_Click(sender As Object, e As RoutedEventArgs)
       Dim dialog As New FileOpenPicker()
       dialog.ViewMode = PickerViewMode.Thumbnail
       dialog.SuggestedStartLocation = PickerLocationId.Desktop
       dialog.FileTypeFilter.Add(".pdf")
    
       ' Allow the user to choose a PDF file to search.
       file = Await dialog.PickSingleFileAsync()
       If file IsNot Nothing Then
           ' Application now has read/write access to the picked file
           tbFile.Text = file.Name
       Else
           tbFile.Text = "Operation cancelled."
       End If
    End Sub
    
    private async void btnFile_Click(object sender, RoutedEventArgs e)
    {
        FileOpenPicker dialog = new FileOpenPicker();
        dialog.ViewMode = PickerViewMode.Thumbnail;
        dialog.SuggestedStartLocation = PickerLocationId.Desktop;
        dialog.FileTypeFilter.Add(".pdf");
    
        // Allow the user to choose a PDF file to search.
        file = await dialog.PickSingleFileAsync();
        if (file != null)
        {
            // Application now has read/write access to the picked file
            tbFile.Text = file.Name;
        }
        else
        {
            tbFile.Text = "Operation cancelled.";
        }
    }
    
  7. Add the following code to the click event of btnFind to start the text search.
    ' Perform the text search.
    Private Sub btnFind_Click(sender As Object, e As RoutedEventArgs)
       ' Load the specified PDF file into c1PdfDocumentSource1, do the search:
       Try
            Await pds.LoadFromFileAsync(file)
              loadedFile = tbFile.Text
       Catch ex As Exception
            Dim dialog = New MessageDialog(ex.Message)
            Await dialog.ShowAsync()
              Return
       End Try
    
       ' Clear the previously found positions, if any:
       listView1.Items.Clear()
    
       ' Init C1FindTextParams with values provided by the user:
       Dim ftp As New C1FindTextParams(tbFind.Text, True, False)
    
       ' Do the search (FindStartAsync is also available):
       tsm.FindStart(0, True, ftp)
    End Sub
    
    // Perform the text search.
    private async void btnFind_Click(object sender, RoutedEventArgs e)
    {
        // Load the specified PDF file into c1PdfDocumentSource1, do the search:
        try
        {
            await pds.LoadFromFileAsync(file);
            loadedFile = tbFile.Text;
        }
        catch (Exception ex)
        {
            var dialog = new MessageDialog(ex.Message);
            await dialog.ShowAsync();
            return;
        }
    
        // Clear the previously found positions, if any:
        listView1.Items.Clear();
    
        // Init C1FindTextParams with values provided by the user:
        C1FindTextParams ftp = new C1FindTextParams(tbFind.Text, true, false);
    
        // Do the search (FindStartAsync is also available):
        tsm.FindStart(0, true, ftp);
    }
    
  8. Add the following code to create a class named SearchItem.
    Public Class SearchItem
       Public Property ID() As Integer
          Get
             Return m_ID
          End Get
          Set
             m_ID = Value
          End Set
       End Property
    Private m_ID As Integer
       Public Property Page() As String
          Get
             Return m_Page
          End Get
          Set
             m_Page = Value
          End Set
       End Property
     Private m_Page As String
        Public Property Bounds() As String
           Get
              Return m_Bounds
           End Get
           Set
              m_Bounds = Value
           End Set
        End Property
    Private m_Bounds As String
        Public Property Position() As String
           Get
              Return m_Position
           End Get
           Set
              m_Position = Value
           End Set
        End Property
    Private m_Position As String
        Public Property NearText() As String
           Get
              Return m_NearText
           End Get
           Set
              m_NearText = Value
           End Set
        End Property
    Private m_NearText As String
    End Class
    
    public class SearchItem
    {
        public int ID { get; set; }
        public string Page { get; set; }
        public string Bounds { get; set; }
        public string Position { get; set; }
        public string NearText { get; set; }
    }
    
  9. Add the following event to update the list of found positions in the UI.
    ' Called when the FoundPositions collection on the C1TextSearchManager
    ' has changed (i.e. some new instances of the search text were found).
    ' Use this to update the list of the found positions in the UI.
    Private Sub Tsm_FoundPositionsChanged(sender As Object, e As EventArgs)
       Dim n As Integer = tsm.FoundPositions.Count
       For i As Integer = listView1.Items.Count To n - 1
           Dim fp As C1FoundPosition = tsm.FoundPositions(i)
           Dim bounds = fp.GetBounds()
    
           listView1.Items.Add(New SearchItem() With { _
              .ID = i + 1, _
              .Page = fp.GetPage().PageNo.ToString(), _
              .Bounds = String.Format("{0}, {1}, {2}, {3}", _
                        CInt(Math.Round(bounds.Left)), _
                        CInt(Math.Round(bounds.Top)), _
                        CInt(Math.Round(bounds.Width)), _
                        CInt(Math.Round(bounds.Height))), _
              .Position = fp.PositionInNearText.ToString(), _
              .NearText = fp.NearText _
            })
       Next
    End Sub
    
    // Called when the FoundPositions collection on the C1TextSearchManager
    //  has changed (i.e. some new instances of the search text were found).
    // Use this to update the list of the found positions in the UI.
    private void Tsm_FoundPositionsChanged(object sender, EventArgs e)
    {
        int n = tsm.FoundPositions.Count;
        for (int i = listView1.Items.Count; i < n; i++)
            {
                C1FoundPosition fp = tsm.FoundPositions[i];
                var bounds = fp.GetBounds();
    
                listView1.Items.Add(new SearchItem
                {
                    ID = i + 1,
                    Page = fp.GetPage().PageNo.ToString(),
                    Bounds = string.Format("{0}, {1}, {2}, {3}",
                    (int)Math.Round(bounds.Left),
                    (int)Math.Round(bounds.Top),
                    (int)Math.Round(bounds.Width),
                    (int)Math.Round(bounds.Height)),
                    Position = fp.PositionInNearText.ToString(),
                    NearText = fp.NearText
                });
            }
    }
    

Step 3: Build and run the project

  1. Press Ctrl+Shift+B to build the project.
  2. Press F5 to run the application.
See Also