Skip to content

Create a PDF Converter using C# and Syncfusion

Become a developer with our complete learning paths
Become a developer with our complete learning paths

Intro

Hello and Welcome to a new Tutorial, This is going to be another special tutorial that is sponsored by this amazing company called Syncfusion!.

.NET, Xamarin, JavaScript, Angular UI components | Syncfusion

What is Syncfusion ?

It is the World’s Best UI Component Suite for Building Powerful Web, Desktop, and Mobile Apps.

In this tutorial, we will be building a Desktop app that converts PDF files to different formats, and we will be using the libraries offered by Syncfusion to achieve that.

We will use their File Converting libraries as well as one of their responsive themes to make our app look amazing :).

So let’s get started!.

Setting up our Project

—Create a new WPF project—

—Add the following Nuget Packages—

 

 

So let’s look at what we have imported.

To be able to convert from Doc(word)to PDF we will need the following Package.

-Syncfusion.DocToPDFConverter.Wpf

To create and Manipulate PDF documents we will need the following Package.

-Syncfusion.Pdf.Wpf

To use the basic Syncfusion UI elements like buttons etc we will need the following package.

-Syncfusion.Shared.WPF

To manage our themes we will add the syncfusion theme manager.

-Syncfusion.SfSkinManager.WPF

And finally, we will add the theme that we will be using which is the Fluent Light theme, and here fluent means that it is responsive.

Syncfusion.Themes.FluentLight.WPF

An additional Nuget package that we will need to work with graphics and images(Not from Syncfusion).

System.Drawing.Common

In the MainWindow.xaml.cs we will need the following namespaces.

using Microsoft.Win32;
//to work with word documents
using Syncfusion.DocIO;
using Syncfusion.DocIO.DLS;
using Syncfusion.DocToPDFConverter;
//to read convert and work with PDF files
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Parsing;
//for our theme
using Syncfusion.SfSkinManager;
using Syncfusion.Themes.FluentLight.WPF;
//to start a proccess we need the diagnostics namespace
using System.Diagnostics;
//to work with images
using System.Drawing;
//to save and read files
using System.IO;
using System.Windows;

Now we need to also import a few assets which are icons for our buttons and our logo.

 

Create a new folder called Images

 

 

Add the following images to it.

 

 

 

Make sure that all images are configured correctly like so.

 

We set the Build Action to Resource and Copy to our Directory if newer, This is to make sure that our images will appear correctly in our UI.

Now let’s start building our UI.

First let’s change the size of our window and add our icon.

Resizing our UI

We will also add a dependency property to our grid which we will link to a grid layout transform that we will use in the code behind to adjust our UI scale when the window size changes!, We will call this property ScaleValue.

Also we need to add an event to our gird for when the size of the grid changes, later on we will use this event to calculate the new size of our gird.

In our MainWindow.Xaml

 

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PDFConverterV2" xmlns:System="clr-namespace:System;assembly=netstandard"
        xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
			 x:Class="PDFConverterV2.MainWindow"
        mc:Ignorable="d"
        Title="Super PDF Converter" Height="307" Width="518"
        x:Name="myMainWindow"
        Icon="Images/favicon.png">

    <Grid Name="MainGrid" SizeChanged="MainGrid_SizeChanged"  VerticalAlignment="Center" HorizontalAlignment="Center" Height="307">
        <Grid.LayoutTransform>
            <ScaleTransform x:Name="ApplicationScaleTransform"
                        CenterX="0"
                        CenterY="0"
                        ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}"
                        ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}" />
        </Grid.LayoutTransform>


           
    </Grid>

</Window>

 

Building our UI

Then let’s add our logo and the name of our app as a label.

 

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PDFConverterSyncfusion"   
xmlns:syncfusion="<http://schemas.syncfusion.com/wpf>" x:Class="PDFConverterSyncfusion.MainWindow"
    x:Name="myMainWindow"
    mc:Ignorable="d"
    Icon="Images/favicon.png"
    Title="Super PDF Converter" Height="300" Width="500">
<Grid>
    <Grid.LayoutTransform>
        <ScaleTransform x:Name="ApplicationScaleTransform"
                        CenterX="0"
                        CenterY="0"
                        ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}"
                        ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}"

                        />
    </Grid.LayoutTransform>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"></ColumnDefinition>
        <ColumnDefinition Width="auto"></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Image Grid.Column="1" Grid.Row="0" Source="Images/Logo.png" Stretch="Fill"
           HorizontalAlignment="Center"
           VerticalAlignment="Top" Height="72" Width="180" Margin="10,10,10,10" />

    <Label Grid.Column="1" Grid.Row="1" Content="Super PDF Converter"
           HorizontalAlignment="Center"
           VerticalAlignment="Center"
           FontWeight="Bold" FontSize="16" Foreground="#FFEE256B" Height="auto" Width="auto" Margin="0,0,0,0" />
   


</Grid>
</Window>

 

 

Then let’s add a button that we will use to open a file selection dialog, a text box to display the path of the selected path, and a dropdown menu to select what type of conversion we want.

But… We won’t use our regular buttons now, instead, we will use the following new UI components from syncfusion.

 

 

 

For this tutorial we will convert from PDF to Doc and vice versa as well as from PNG to PDF, you can add tons of conversions on your own later :).

Finally lets add the convert button itself!.

 

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PDFConverterSyncfusion"   
xmlns:syncfusion="<http://schemas.syncfusion.com/wpf>" x:Class="PDFConverterSyncfusion.MainWindow"
    x:Name="myMainWindow"
    mc:Ignorable="d"
    Icon="Images/favicon.png"
    Title="Super PDF Converter" Height="300" Width="500">
<Grid>
    <Grid.LayoutTransform>
        <ScaleTransform x:Name="ApplicationScaleTransform"
                        CenterX="0"
                        CenterY="0"
                        ScaleX="{Binding ElementName=myMainWindow, Path=ScaleValue}"
                        ScaleY="{Binding ElementName=myMainWindow, Path=ScaleValue}"

                        />
    </Grid.LayoutTransform>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"></ColumnDefinition>
        <ColumnDefinition Width="auto"></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition Height="auto"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Image Grid.Column="1" Grid.Row="0" Source="Images/Logo.png" Stretch="Fill"
           HorizontalAlignment="Center"
           VerticalAlignment="Top" Height="72" Width="180" Margin="10,10,10,10" />

    <Label Grid.Column="1" Grid.Row="1" Content="Super PDF Converter"
           HorizontalAlignment="Center"
           VerticalAlignment="Center"
           FontWeight="Bold" FontSize="16" Foreground="#FFEE256B" Height="auto" Width="auto" Margin="0,0,0,0" />
    <syncfusion:ButtonAdv Content="Select File" SmallIcon="/Images/Select File Icon.png"
                          HorizontalAlignment="Left" Height="35" Label="Select File" Margin="10,10,10,10"
                          Grid.Row="2" VerticalAlignment="Center" Width="115"
                          Background="#FFEF2F5A"
                          Foreground="White"
                          />

    <TextBox x:Name="pathTextBox" Grid.Column="1" Grid.Row="2" TextWrapping="NoWrap" AcceptsReturn="False"
             Margin="10,10,10,10"
             />

    <syncfusion:ComboBoxAdv x:Name="conversionDropDown" Grid.Column="2" Grid.Row="2" AllowMultiSelect="False"
                            DefaultText="Select"  Foreground="White" Background="#FFEF2F5A" Width="115"
                            Margin="10,10,10,10"
                            >
        <syncfusion:ComboBoxItemAdv Content="  Doc to PDF"/>
        <syncfusion:ComboBoxItemAdv Content="  PDF to Doc"/>
        <syncfusion:ComboBoxItemAdv Content="  PNG to PDF"/>
    </syncfusion:ComboBoxAdv>


</Grid>
</Window>

 

 

Our app should look like this..

Now back to our MainWindow.xaml.cs

First thing in our code behind let’s code the logic to resize our UI.

let’s add a new dependency property

 

//dependecy property called ScaleValue which is of type double and has two events in it's metadata, to adjust the scale
public static readonly DependencyProperty ScaleValueProperty = DependencyProperty.Register("ScaleValue", typeof(double), typeof(MainWindow), 
	new UIPropertyMetadata(1.0, new PropertyChangedCallback(OnScaleValueChanged), new CoerceValueCallback(OnCoerceScaleValue)));

Then let’s define these two events we added to our metadata.

private static object OnCoerceScaleValue(DependencyObject o, object value)
  {
      //set the mainWindow object
      MainWindow mainWindow = o as MainWindow;
      if (mainWindow != null)
      {
          //call the OnCoerceScaleValue and pass it the value we recieved as a double
          return mainWindow.OnCoerceScaleValue((double)value);
      }
      else
      {
          return value;
      }
  }

  private static void OnScaleValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
  {
      //set the mainWindow object
      MainWindow mainWindow = o as MainWindow;

      if (mainWindow != null)
      {
          //call the OnScaleValueChanged and pass it both the old value and the new value 
          mainWindow.OnScaleValueChanged((double)e.OldValue, (double)e.NewValue);
      }
  }

 

Now let’s add the required methods we are calling from within our callback methods and also the size calculation logic

public double OnCoerceScaleValue(double value)
{
    //for protection check if the double value is valid
    if (double.IsNaN(value))
    {
        //if the double is not a number return 1 for the scale
        return 1.0f;
    }
    //we don't want to scale down our UI below 0.1 so we will get the max value between 0.1 and the current scale
    value = Math.Max(0.1, value);
    return value;
}

//since we need to actually add a call back for the OnScaleValueChanged, but we will be caclulating our scale
//whenever we set or get our dependecy property
public void OnScaleValueChanged(double oldValue, double newValue) { }

//define the ScaleValue property, which corrsponds to our depedncy property name
public double ScaleValue
{
    get => (double)GetValue(ScaleValueProperty);
    set => SetValue(ScaleValueProperty, value);
}


//whenever we change the scale of our grid, call the CalculateScale method
private void MainGrid_SizeChanged(object sender, EventArgs e) => CalculateScale();

private void CalculateScale()
{
    //get our current height and width and divide it by our old height and width to get the new ratio
    double yScale = ActualHeight / 307;
    double xScale = ActualWidth / 518f;
    //our scaling should depend on the min between the width and height so our UI elements don't overlap
    double value = Math.Min(xScale, yScale);
    //set our ScaleValue (dependency property)
    ScaleValue = (double)OnCoerceScaleValue(myMainWindow, value);
}

 

—test the resize logic—

 

Adding our Converting Logic

 

Now let’s code our button click events!.

Let’s code our Select File button event.

 

private void Button_Click(object sender, RoutedEventArgs e)
    {
        //Create file dialog and configure to open csv files only
        OpenFileDialog filelDialog = new OpenFileDialog();
        // csvFielDialog.Filter = "CSF files(*.csv)|*.csv";

        //Show the dialog to the user
        bool? result = filelDialog.ShowDialog();

        //If the user selected something perform the actions with the file
        if (result.HasValue && result.Value)
        {
						//we will only set the file name and path to our pathTexBox
            pathTextBox.Text = filelDialog.FileName;
        }
    }

Once the conversion is done, we want to open the path of our converted file.

So let’s add a method for that!.

This method will only take the path of the file we want, and it will open it’s folder in the windows file explorer.

 

private void OpenFolder(string folderPath)
  {
      //create a new proccess info to start the explorer.exe which will open file explorer in windows
      ProcessStartInfo startInfo = new ProcessStartInfo()
      {
          //we want the folder path only without the file name
          //so we take a substring starting from 0 till the last index of \ 
          Arguments = folderPath.Substring(0,folderPath.LastIndexOf('\\')),
          FileName = "explorer.exe",
      };
      //start the proccess
      Process.Start(startInfo);
  }

 

 

Now we are ready to code our Convert Button Click event method.

It will be a switch statement to determine which type of conversion to use and for every conversion, we will create a method. We will need 3 void methods that take a string which is the file name itself.

 

 

private void Button_Click_1(object sender, RoutedEventArgs e)
  {
      //check if the textbox for the path is empty
      if (pathTextBox.Text == string.Empty)
      {
          //display an warning and exit the method
          MessageBox.Show("Please select a file");
          return;
      }
      //switch over the selected conversion type, index of -1 means nothing is selected 
      switch (conversionDropDown.SelectedIndex)
      {
          case 0://"Doc to PDF":
              ConvertDocToPDF(pathTextBox.Text);

              break;
          case 1:// "PDF to Doc":
              ConvertPDFtoDOC(pathTextBox.Text);

              break;
          case 2:// "PNG to DOC":
              ConvertPNGtoPDF(pathTextBox.Text);

              break;
          default:
              MessageBox.Show("Please select an option");
              return;
      }
      //open the folder containing the converted file in file explorer
      OpenFolder(pathTextBox.Text);
  }

 

 

Now let’s create our conversion methods

ConvertPNGtoPDF

 

private void ConvertPNGtoPDF(string pngPath)
  {
     
      //Create an instance of pdf document 
      PdfDocument pdfDoc = new PdfDocument();
      //read the png image and itno a pdf image object
      PdfImage pdfImage = PdfImage.FromStream(new FileStream(pngPath, FileMode.Open));
      //create a new pdfpage
      PdfPage pdfPage = new PdfPage();
      //add a new section to our pdf
      //because a pdf file contains sections, and pdf sections contains pages which will contain our image
      PdfSection pdfSection = pdfDoc.Sections.Add();
      //add the pdf page into the list of pages of our pdf section
      pdfSection.Pages.Insert(0, pdfPage);
      //draw the image into our pdf page
      pdfPage.Graphics.DrawImage(pdfImage, 0, 0);


      //Save the PDF file
      //the name of the new file will be the same name of the file before conversion but with the new file extension
      string newPNGPath = pngPath.Split('.')[0] + ".pdf";
      pdfDoc.Save(newPNGPath);

      //Close the instance of document objects

      pdfDoc.Close(true);
  }

ConvertPDFToDoc

private void ConvertPDFtoDOC(string pdfPath)
  {
      //Creates a new Word document.
      WordDocument wordDocument = new WordDocument();

      //Adds new section to the document.
      IWSection section = wordDocument.AddSection();

      //Sets the page margins to zero.
      section.PageSetup.Margins.All = 0;

      //Adds new paragraph to the section.
      IWParagraph firstParagraph = section.AddParagraph();
      
      //create a new SizeF struct to store the value of the page width and size
      SizeF defaultPageSize = new SizeF(wordDocument.LastSection.PageSetup.PageSize.Width, 
					wordDocument.LastSection.PageSetup.PageSize.Height);

      //Loads the PDF document from the given file path.
      using (PdfLoadedDocument loadedDocument = new PdfLoadedDocument(pdfPath))
      {
          //for every loded page in our document
          for (int i = 0; i < loadedDocument.Pages.Count; i++)
          {
              //Exports the PDF document page as image with the given size.
              using (var image = loadedDocument.ExportAsImage(i, defaultPageSize, false))
              {
                  //Adds image to the paragraph
                  IWPicture picture = firstParagraph.AppendPicture(image);

                  //Sets width and height for the image.
                  picture.Width = image.Width;
                  picture.Height = image.Height;
              }
          }
      };
      //the name of the new file will be the same name of the file before conversion but with the new file extension
      string newPDFPath = pdfPath.Split('.')[0] + ".docx";
      //Saves the Word document
      wordDocument.Save(newPDFPath);

      //Close the document.
      wordDocument.Dispose();
    

  }

And Finally ConvertDocToPDF

private void ConvertDocToPDF(string docPath)
  {
      //create a new word document object using the document path
      WordDocument wordDocument = new WordDocument(docPath, FormatType.Automatic);


      //Create an instance of DocToPDFConverter

      DocToPDFConverter converter = new DocToPDFConverter();

      //Convert Word document into PDF document

      PdfDocument pdfDocument = converter.ConvertToPDF(wordDocument);

      //Save the PDF file
      string newPDFPath = docPath.Split('.')[0] + ".pdf";
      pdfDocument.Save(newPDFPath);

      //Close the instance of document objects

      pdfDocument.Close(true);

      wordDocument.Close();

    
  }

now the last thing we want to do is to apply our theme.

In the constructor of our MainWindow before we call the InitalizeComponents method.

public MainWindow()
  {
			//create a new theme object
      FluentTheme fluentTheme = new FluentTheme()
      {
          //set the name of the theme
          ThemeName = "FluentLight",
          //set the hover and press effects (animation)
          HoverEffectMode = HoverEffect.None,
          PressedEffectMode = PressedEffect.Glow,
          //set the background to be acrylic transparent
          ShowAcrylicBackground = false
      };
     
      //create a new theme settings
      FluentLightThemeSettings themeSettings = new FluentLightThemeSettings();
      //set the font size to 16 and the font to barlow
      themeSettings.BodyFontSize = 16;
      themeSettings.FontFamily = new System.Windows.Media.FontFamily("Barlow");
      //register the theme settings
      SfSkinManager.RegisterThemeSettings("FluentLight", themeSettings);
      //set the theme to the syncfusion skin manager, this refers to this window
      SfSkinManager.SetTheme(this, fluentTheme);
      //Note: it is important to initalize our components after we have configured our theme
      InitializeComponent();

  }

Resizing

private void myMainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            {
                myMainWindow.Width = e.NewSize.Width;
                myMainWindow.Height = e.NewSize.Height;

                double xChange = 1, yChange = 1;

                if (e.PreviousSize.Width != 0)
                    xChange = (e.NewSize.Width / e.PreviousSize.Width);

                if (e.PreviousSize.Height != 0)
                    yChange = (e.NewSize.Height / e.PreviousSize.Height);

                foreach (FrameworkElement fe in myGrid.Children)
                {
                    if (fe is Grid == false)
                    {
                        fe.Height = fe.ActualHeight * yChange;
                        fe.Width = fe.ActualWidth * xChange;

                        Canvas.SetTop(fe, Canvas.GetTop(fe) * yChange);
                        Canvas.SetLeft(fe, Canvas.GetLeft(fe) * xChange);

                    }
                }
            }
        }

Test the app :)..

 

I hope you enjoyed this tutorial and learned something.

You can download the sourcecode from Github

https://github.com/tutorialseu/WPF-PDF-Converter-with-Syncfusion

or watch this tutorial on YouTube.

Lost in coding? Discover our Learning Paths!
Lost in coding? Discover our Learning Paths!
Enter your email and we will send you the PDF guide:
Enter your email and we will send you the PDF guide