How to Start Tutorials Troubleshooting Main Operations Convert PDF Read PDF Edit PDF PDF Report Generator Work with PDF Modules PDF Document PDF Pages Text Image Graph & Path Annotation, Markup & Drawing Redaction Security Digital Signature Forms Watermark Bookmark Link File Attachment File Metadata Printing Work with Other SDKs Barcode read Barcode create OCR Twain

WPF PDF C# Library
How to compress PDF with password protected in C# WPF (Core) Windows application?


Complete step by step tutorial to compress PDF file with password protected in WPF Windows application using C#.



XDoc.PDF for C# library is an easy to use PDF C# library to read, compress, apply password security on PDFs in .NET Core Windows (WinForms, WPF) application and ASP.NET Core web apps.

In this C# tutorial will guide you how to build a PDF compress and passsword protect app in a new C# Windows Presentation Foundation (WPF) app with Visual Studio 2022. You will publish the generated WPF application to your local folder. By the end of this tutorial, you'll have a simple WPF Window app that compress PDF images and add password to protect it.

Using PDF C# viewer library we will:

  • Create a WPF (.NET Core) application using C#.NET
  • Preview all PDF files in one folder



Download and Install XDoc.PDF WPF C# library


  1. Download XDoc.PDF WPF C# library
  2. Install C# library to compress, process PDF files in .NET Core WPF projects
  3. Step by Step Tutorial






How to compress PDF using C# in WPF (.NET Core) application?



1. Create a new WPF project with XDoc.PDF library installed

Here we will create a new WPF project with name "RasterEdgePDFWPFDemo".

We have provided step by step guide to install XDoc.PDF library on a new WPF (.NET Core) project. Please view here:
How to create a new WPF app using Visual Studio 2022 to process PDF?





2. Design the WPF app user interface

Select MainWindow.xaml in the Solution Explorer to open the WPF Designer.

XAML View


Design View


2.1 Adjust the attributes of the Window tag as below.

XAML

<Window x:Class="RasterEdgePDFWPFDemo.MainWindow"
        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:RasterEdgePDFWPFDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid>

    </Grid>
</Window>



2.2 add a Button control in the tag for browsing the target PDF file.

XAML

<Button Content="Open File" Width="90" Height="20" Margin="40,30,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>


Design View



2.3 add a Textbox control to show the path of the target PDF file; and set this Textbox to read-only.

XAML

<TextBox Name="InputFilePath" Text="" Width="600" Height="18" Margin="160,31,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
         TextWrapping="NoWrap" IsReadOnly="True"/>


Design View



2.4 add three more Button controls, two for saving the optimized PDF file (with or without password) and the last one for closing the application.

XAML

<Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Content="Close" Width="220" Height="20" Margin="540,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>


Design View



2.5 add a GroupBox control for image optimization settings.

XAML

<GroupBox Header="Imaging Settings" Width="720" Height="340" Margin="40,60,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Canvas>
        <GroupBox Header="Color Images:" Width="698" Height="95" Margin="5,5,0,0">
            <Canvas>
                <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                <ComboBox Name="ColorDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                    <ComboBoxItem Content="Off"/>
                    <ComboBoxItem Content="Average Downsampling to"/>
                    <ComboBoxItem Content="Subsampling to"/>
                    <ComboBoxItem Content="Bicubic Downsampling to"/>
                </ComboBox>
                <TextBox Name="ColorTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                <TextBox Name="ColorMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                <ComboBox Name="ColorCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="3">
                    <ComboBoxItem Content="ASCII85"/>
                    <ComboBoxItem Content="ASCIIHex"/>
                    <ComboBoxItem Content="CCITTFax"/>
                    <ComboBoxItem Content="DCT"/>
                    <ComboBoxItem Content="Flate"/>
                    <ComboBoxItem Content="JBIG2"/>
                    <ComboBoxItem Content="JPX"/>
                    <ComboBoxItem Content="LZW"/>
                    <ComboBoxItem Content="NoFilter"/>
                    <ComboBoxItem Content="RunLength"/>
                </ComboBox>
                <Label Content="Quality:" Canvas.Left="260" Canvas.Top="40"/>
                <ComboBox Name="ColorJPEGQuality" Width="120" Canvas.Left="320" Canvas.Top="43" SelectedIndex="2">
                    <ComboBoxItem Content="Minimum"/>
                    <ComboBoxItem Content="Low"/>
                    <ComboBoxItem Content="Medium"/>
                    <ComboBoxItem Content="High"/>
                    <ComboBoxItem Content="Maximum"/>
                </ComboBox>
            </Canvas>
        </GroupBox>
        <GroupBox Header="Grayscale Images:" Width="698" Height="95" Margin="5,100,0,0">
            <Canvas>
                <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                <ComboBox Name="GrayDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                    <ComboBoxItem Content="Off"/>
                    <ComboBoxItem Content="Average Downsampling to"/>
                    <ComboBoxItem Content="Subsampling to"/>
                    <ComboBoxItem Content="Bicubic Downsampling to"/>
                </ComboBox>
                <TextBox Name="GrayTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                <TextBox Name="GrayMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                <ComboBox Name="GrayCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="3">
                    <ComboBoxItem Content="ASCII85"/>
                    <ComboBoxItem Content="ASCIIHex"/>
                    <ComboBoxItem Content="CCITTFax"/>
                    <ComboBoxItem Content="DCT"/>
                    <ComboBoxItem Content="Flate"/>
                    <ComboBoxItem Content="JBIG2"/>
                    <ComboBoxItem Content="JPX"/>
                    <ComboBoxItem Content="LZW"/>
                    <ComboBoxItem Content="NoFilter"/>
                    <ComboBoxItem Content="RunLength"/>
                </ComboBox>
                <Label Content="Quality:" Canvas.Left="260" Canvas.Top="40"/>
                <ComboBox Name="GrayJPEGQuality" Width="120" Canvas.Left="320" Canvas.Top="43" SelectedIndex="2">
                    <ComboBoxItem Content="Minimum"/>
                    <ComboBoxItem Content="Low"/>
                    <ComboBoxItem Content="Medium"/>
                    <ComboBoxItem Content="High"/>
                    <ComboBoxItem Content="Maximum"/>
                </ComboBox>
            </Canvas>
        </GroupBox>
        <GroupBox Header="Monochrome Images:" Margin="5,195,0,0" Width="698" Height="95">
            <Canvas>
                <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                <ComboBox Name="MonoDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                    <ComboBoxItem Content="Off"/>
                    <ComboBoxItem Content="Average Downsampling to"/>
                    <ComboBoxItem Content="Subsampling to"/>
                    <ComboBoxItem Content="Bicubic Downsampling to"/>
                </ComboBox>
                <TextBox Name="MonoTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                <TextBox Name="MonoMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>
                <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                <ComboBox Name="MonoCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="2">
                    <ComboBoxItem Content="ASCII85"/>
                    <ComboBoxItem Content="ASCIIHex"/>
                    <ComboBoxItem Content="CCITTFax"/>
                    <ComboBoxItem Content="DCT"/>
                    <ComboBoxItem Content="Flate"/>
                    <ComboBoxItem Content="JBIG2"/>
                    <ComboBoxItem Content="JPX"/>
                    <ComboBoxItem Content="LZW"/>
                    <ComboBoxItem Content="NoFilter"/>
                    <ComboBoxItem Content="RunLength"/>
                </ComboBox>
            </Canvas>
        </GroupBox>
        <Label Content="All units are in pixels per inch (ppi)" Canvas.Left="500" Canvas.Top="292"/>
    </Canvas>
</GroupBox>


Design View



2.6 add a GroupBox control for password settings.

XAML

<GroupBox Header="Password Settings" Width="720" Height="72" Margin="40,405,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" >
    <Canvas>
        <Label Content="Owner password (required):" Width="160" Height="28" Canvas.Left="10" Canvas.Top="10"/>
        <TextBox Name="OwnerPassword" Text="12345678" Width="120" Height="18" Canvas.Top="15" Canvas.Left="170" TextWrapping="NoWrap"/>
        <Label Content="User password (optional):" Width="160" Height="28" Canvas.Left="370" Canvas.Top="10"/>
        <TextBox Name="UserPassword" Text="" Width="120" Height="18" Canvas.Top="15" Canvas.Left="530" TextWrapping="NoWrap"/>
    </Canvas>
</GroupBox>


Design View





3. Add event handler to controls



3.1 add "Click" event handler for four Button controls with name "Button_Click", "Button_Click_1", "Button_Click_2" and "Button_Click_3".

XAML (old)

<Button Content="Open File" Width="90" Height="20" Margin="40,30,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
...
<Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Button Content="Close" Width="220" Height="20" Margin="540,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>


XAML (new)
<Button Content="Open File" Width="90" Height="20" Margin="40,30,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click"/><Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_1"/>
<Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_2"/>
<Button Content="Close" Width="220" Height="20" Margin="540,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_3"/>


XAML View



Then, add four empty methods (as below) to the code-behind file "MainWindow.xaml.cs". The implementation of these methods would be added in the next section (Section 6).

private void Button_Click(object sender, RoutedEventArgs e)
{
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
}

private void Button_Click_3(object sender, RoutedEventArgs e)
{
}


XAML View



3.2 add "PreviewTextInput" event handler to those six PPI textbox in the "Imaging Settings"; and set ALL to the same method "TextBox_PreviewTextInput".

XAML (old)

<TextBox Name="ColorTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/><TextBox Name="ColorMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>
...
<TextBox Name="GrayTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/>
...
<TextBox Name="GrayMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>
...
<TextBox Name="MonoTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"/>
...
<TextBox Name="MonoMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"/>


XAML (new)
<TextBox Name="ColorTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>
...
<TextBox Name="ColorMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>
...
<TextBox Name="GrayTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>
...
<TextBox Name="GrayMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>
...
<TextBox Name="MonoTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>
...
<TextBox Name="MonoMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
         PreviewTextInput="TextBox_PreviewTextInput"/>




Then, add the following method to the code-behind file "MainWindow.xaml.cs", which limits the input character in the Textbox to digits.

//  To ignore non-digit input for those textboxes of resolutions.
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    bool isValid = true;
    foreach (char c in e.Text)
    {
        if (!Char.IsDigit(c))
        {
            isValid = false;
            break;
        }
    }
    e.Handled = !isValid;
}




3.3 add attribute "IsEnabled" to two save file Buttons and declare a binding to them.

XAML (old)

<Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_1"/>
<Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_2"/>


XAML (new)
<Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_1"
        IsEnabled="{Binding ElementName=InputFilePath, Path=Text.Length, Mode=OneWay}"/>
<Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
        Click="Button_Click_2">
    <Button.IsEnabled>
        <MultiBinding Converter="{StaticResource IsEnabledConverter}">
            <Binding ElementName="InputFilePath" Path="Text.Length"/>
            <Binding ElementName="OwnerPassword" Path="Text.Length"/>
        </MultiBinding>
    </Button.IsEnabled>
</Button>




3.3a add the app-wide resource for the multi-binding of the Button "Compress PDF with password".

Add a "New Item" to the project.



Add a Class with name "IsEnabledConverter.cs".



Copy all following contents to the class file.

using System.Globalization;
using System.Windows.Data;

namespace RasterEdgePDFWPFDemo
{
    public class IsEnabledConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            foreach (var value in values)
            {
                switch (value)
                {
                    case int len when len == 0:
                        return false;
                }
            }
            return true;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return new object[0];
        }
    }
}


Select the file "App.xaml" in the Solution Explorer, and add a new entry with key name "IsEnabledConverter" to the tag <Application.Resources>.
<Application x:Class="RasterEdgePDFWPFDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:RasterEdgePDFWPFDemo"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:IsEnabledConverter x:Key="IsEnabledConverter"/>
    </Application.Resources>
</Application>




Note:

There will be no further changes to the XAML file "MainWindow.xaml".





4. Use code-behind to implement four Button Click handlers



Method: Button_Click

Browse a target PDF file with an open file dialog (Microsoft.Win32.OpenFileDialog).

private void Button_Click(object sender, RoutedEventArgs e)
{
    OpenFileDialog openFileDialog = new OpenFileDialog();
    openFileDialog.Filter = "All files (*.pdf)|*.pdf";
    openFileDialog.RestoreDirectory = true;

    if (openFileDialog.ShowDialog() ?? false)
    {
        String filePath = openFileDialog.FileName;
        this.InputFilePath.Text = filePath;
    }
}



Method: Button_Click_1

Button_Click_1 Save the target PDF file with the specified settings (without password) by using the local method "saveOptimizedFile(bool withPassword)".

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    try
    {
        if (saveOptimizedFile(false) == 0)
            MessageBox.Show("Save file successful.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}



Method: Button_Click_2

Save the target PDF file with the specified settings (with password) by using the local method "saveOptimizedFile(bool withPassword)".

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    try
    {
        if (saveOptimizedFile(true) == 0)
            MessageBox.Show("Save file successful.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}



Method: Button_Click_3

Close the application.

private void Button_Click_3(object sender, RoutedEventArgs e)
{
    this.Close();
}




List of all remained methods those implement the method "saveOptimizedFile".

Use a save file dialog to get the output file path and save the optimized PDF file.

private int saveOptimizedFile(bool withPassword)
private void saveToFile(String inputFilePath, String outputFilePath, bool withPassword, String userPassword, String ownerPassword)



Utility methods to create PDF optimize option object from those Controls.

private PDFOptimizeOptions getOptimizeOptions()
private float getResolution(string ppi)
private ImageDownsampleMode getDownSample(string downSample)
private PDFCompression getCompression(string compression)
private JPEGImageQualityLevel getQualityLevel(string qualityLevel)






5. It is done. Now press "Ctrl+F5" to run the project.







6. Screenshot for the Demo application





Press "Open File" button to browser the target PDF file.



Press "Compress PDF to new file" or "Compress PDF with password" button to save the optimized file; and then it would show a message box after file has been saved.



Note: button "Compress PDF with password" is disabled if owner password is empty.





7. Publish the WPF application to a folder.



7.1 In Solution Explorer, right-click the project and choose "Publish" to open the Publish wizard.



Select "Folder" option in the Publish dialog, and then press button "Next".





7.2 Provide the path of the target folder (e.g. "C:\Demos\RasterEdgePDFWPFDemo") to publish the application and click button "Finish" to complete the wizard.



It creates a new publish profile file in the folder "{ProjectDir}\Properties\PublishProfiles".



7.3 Click button "Publish" and Visual Studio would deploy the application to the specified path.



Then, waiting for publish succeeded.



7.4 Go to the output folder ("C:\Demos\RasterEdgePDFWPFDemo") and click the EXE file to run the application.





Appendix



Appendix A: MainWindow.xaml

<Window x:Class="RasterEdgePDFWPFDemo.MainWindow"
        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:RasterEdgePDFWPFDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid>
        <Button Content="Open File" Width="90" Height="20" Margin="40,30,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
                Click="Button_Click"/>
        <TextBox Name="InputFilePath" Text="" Width="600" Height="18" Margin="160,31,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
                 TextWrapping="NoWrap" IsReadOnly="True"/>
        <Button Content="Compress PDF to new file" Width="220" Height="20" Margin="40,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
                Click="Button_Click_1"
                IsEnabled="{Binding ElementName=InputFilePath, Path=Text.Length, Mode=OneWay}"/>
        <Button Content="Compress PDF with password" Width="220" Height="20" Margin="290,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
                Click="Button_Click_2">
            <Button.IsEnabled>
                <MultiBinding Converter="{StaticResource IsEnabledConverter}">
                    <Binding ElementName="InputFilePath" Path="Text.Length"/>
                    <Binding ElementName="OwnerPassword" Path="Text.Length"/>
                </MultiBinding>
            </Button.IsEnabled>
        </Button>
        <Button Content="Close" Width="220" Height="20" Margin="540,505,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
                Click="Button_Click_3"/>
        <GroupBox Header="Imaging Settings" Width="720" Height="340" Margin="40,60,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas>
                <GroupBox Header="Color Images:" Width="698" Height="95" Margin="5,5,0,0">
                    <Canvas>
                        <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                        <ComboBox Name="ColorDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                            <ComboBoxItem Content="Off"/>
                            <ComboBoxItem Content="Average Downsampling to"/>
                            <ComboBoxItem Content="Subsampling to"/>
                            <ComboBoxItem Content="Bicubic Downsampling to"/>
                        </ComboBox>
                        <TextBox Name="ColorTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                        <TextBox Name="ColorMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                        <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                        <ComboBox Name="ColorCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="3">
                            <ComboBoxItem Content="ASCII85"/>
                            <ComboBoxItem Content="ASCIIHex"/>
                            <ComboBoxItem Content="CCITTFax"/>
                            <ComboBoxItem Content="DCT"/>
                            <ComboBoxItem Content="Flate"/>
                            <ComboBoxItem Content="JBIG2"/>
                            <ComboBoxItem Content="JPX"/>
                            <ComboBoxItem Content="LZW"/>
                            <ComboBoxItem Content="NoFilter"/>
                            <ComboBoxItem Content="RunLength"/>
                        </ComboBox>
                        <Label Content="Quality:" Canvas.Left="260" Canvas.Top="40"/>
                        <ComboBox Name="ColorJPEGQuality" Width="120" Canvas.Left="320" Canvas.Top="43" SelectedIndex="2">
                            <ComboBoxItem Content="Minimum"/>
                            <ComboBoxItem Content="Low"/>
                            <ComboBoxItem Content="Medium"/>
                            <ComboBoxItem Content="High"/>
                            <ComboBoxItem Content="Maximum"/>
                        </ComboBox>
                    </Canvas>
                </GroupBox>
                <GroupBox Header="Grayscale Images:" Width="698" Height="95" Margin="5,100,0,0">
                    <Canvas>
                        <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                        <ComboBox Name="GrayDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                            <ComboBoxItem Content="Off"/>
                            <ComboBoxItem Content="Average Downsampling to"/>
                            <ComboBoxItem Content="Subsampling to"/>
                            <ComboBoxItem Content="Bicubic Downsampling to"/>
                        </ComboBox>
                        <TextBox Name="GrayTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                        <TextBox Name="GrayMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                        <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                        <ComboBox Name="GrayCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="3">
                            <ComboBoxItem Content="ASCII85"/>
                            <ComboBoxItem Content="ASCIIHex"/>
                            <ComboBoxItem Content="CCITTFax"/>
                            <ComboBoxItem Content="DCT"/>
                            <ComboBoxItem Content="Flate"/>
                            <ComboBoxItem Content="JBIG2"/>
                            <ComboBoxItem Content="JPX"/>
                            <ComboBoxItem Content="LZW"/>
                            <ComboBoxItem Content="NoFilter"/>
                            <ComboBoxItem Content="RunLength"/>
                        </ComboBox>
                        <Label Content="Quality:" Canvas.Left="260" Canvas.Top="40"/>
                        <ComboBox Name="GrayJPEGQuality" Width="120" Canvas.Left="320" Canvas.Top="43" SelectedIndex="2">
                            <ComboBoxItem Content="Minimum"/>
                            <ComboBoxItem Content="Low"/>
                            <ComboBoxItem Content="Medium"/>
                            <ComboBoxItem Content="High"/>
                            <ComboBoxItem Content="Maximum"/>
                        </ComboBox>
                    </Canvas>
                </GroupBox>
                <GroupBox Header="Monochrome Images:" Margin="5,195,0,0" Width="698" Height="95">
                    <Canvas>
                        <Label Content="Downsample:" Canvas.Left="10" Canvas.Top="10"/>
                        <ComboBox Name="MonoDownsampleMode" Canvas.Left="100" Canvas.Top="11" Width="200" SelectedIndex="3">
                            <ComboBoxItem Content="Off"/>
                            <ComboBoxItem Content="Average Downsampling to"/>
                            <ComboBoxItem Content="Subsampling to"/>
                            <ComboBoxItem Content="Bicubic Downsampling to"/>
                        </ComboBox>
                        <TextBox Name="MonoTargetPPI" Text="150" Width="40" Canvas.Left="320" Canvas.Top="15" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi for images above" Canvas.Left="365" Canvas.Top="10"/>
                        <TextBox Name="MonoMaximumPPI" Canvas.Left="492" Text="225" Canvas.Top="15" Width="40" TextAlignment="Center" MaxLength="3"
                                 PreviewTextInput="TextBox_PreviewTextInput"/>
                        <Label Content="ppi." Canvas.Left="537" Canvas.Top="10"/>
                        <Label Content="Compression:" Canvas.Left="10" Canvas.Top="40"/>
                        <ComboBox Name="MonoCompression" Width="120" Canvas.Left="100" Canvas.Top="43" SelectedIndex="2">
                            <ComboBoxItem Content="ASCII85"/>
                            <ComboBoxItem Content="ASCIIHex"/>
                            <ComboBoxItem Content="CCITTFax"/>
                            <ComboBoxItem Content="DCT"/>
                            <ComboBoxItem Content="Flate"/>
                            <ComboBoxItem Content="JBIG2"/>
                            <ComboBoxItem Content="JPX"/>
                            <ComboBoxItem Content="LZW"/>
                            <ComboBoxItem Content="NoFilter"/>
                            <ComboBoxItem Content="RunLength"/>
                        </ComboBox>
                    </Canvas>
                </GroupBox>
                <Label Content="All units are in pixels per inch (ppi)" Canvas.Left="500" Canvas.Top="292"/>
            </Canvas>
        </GroupBox>
        <GroupBox Header="Password Settings" Width="720" Height="72" Margin="40,405,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" >
            <Canvas>
                <Label Content="Owner password (required):" Width="160" Height="28" Canvas.Left="10" Canvas.Top="10"/>
                <TextBox Name="OwnerPassword" Text="12345678" Width="120" Height="18" Canvas.Top="15" Canvas.Left="170" TextWrapping="NoWrap"/>
                <Label Content="User password (optional):" Width="160" Height="28" Canvas.Left="370" Canvas.Top="10"/>
                <TextBox Name="UserPassword" Text="" Width="120" Height="18" Canvas.Top="15" Canvas.Left="530" TextWrapping="NoWrap"/>
            </Canvas>
        </GroupBox>
    </Grid>
</Window>



Appendix B: MainWindow.xaml.cs

using System.IO;
using System.Windows;
using System.Windows.Input;
using Microsoft.Win32;
using RasterEdge.XDoc.PDF;

namespace RasterEdgePDFWPFDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        //  To ignore non-digit input for those textboxes of resolutions.
        private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            bool isValid = true;
            foreach (char c in e.Text)
            {
                if (!Char.IsDigit(c))
                {
                    isValid = false;
                    break;
                }
            }
            e.Handled = !isValid;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "All files (*.pdf)|*.pdf";
            openFileDialog.RestoreDirectory = true;

            if (openFileDialog.ShowDialog() ?? false)
            {
                String filePath = openFileDialog.FileName;
                this.InputFilePath.Text = filePath;
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            try
            {
                if (saveOptimizedFile(false) == 0)
                    MessageBox.Show("Save file successful.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            try
            {
                if (saveOptimizedFile(true) == 0)
                    MessageBox.Show("Save file successful.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        #region Save optimized file with/without password

        //  Return error code. 0 for success; otherwise, failed.
        private int saveOptimizedFile(bool withPassword)
        {
            String inputFilePath = this.InputFilePath.Text;
            if (String.IsNullOrEmpty(inputFilePath))
                throw new Exception("File path is null or empty.");
            if (!File.Exists(inputFilePath))
                throw new Exception("File does not exist. '" + inputFilePath + "'");

            //  Get passwords from controls if required.
            String userPassword = "";
            String ownerPassword = "";
            if (withPassword)
            {
                userPassword = this.UserPassword.Text;
                ownerPassword = this.OwnerPassword.Text;
                if (String.IsNullOrEmpty(ownerPassword))
                    throw new Exception("Owner password cannot be omitted.");
                //  User paasword can be empty
                if (userPassword == null)
                    userPassword = "";
            }

            //  To select output file path.
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "PDF files (*.pdf)|*.pdf";
            saveFileDialog.RestoreDirectory = true;

            if (saveFileDialog.ShowDialog() ?? false)
            {
                String outputFilePath = saveFileDialog.FileName;
                saveToFile(inputFilePath, outputFilePath, withPassword, userPassword, ownerPassword);
                return 0;
            }

            return -1;
        }

        private void saveToFile(String inputFilePath, String outputFilePath,
                                bool withPassword, String userPassword, String ownerPassword)
        {
            PDFDocument doc = new PDFDocument(inputFilePath);
            //  Get optimize settings from control and apply to the target file.
            PDFOptimizeOptions options = getOptimizeOptions();

            MemoryStream memStream = new MemoryStream();
            PDFOptimizer.Optimize(inputFilePath, outputFilePath, options);

            if (withPassword)
            {
                //  Apply password to the output file.
                PasswordSetting setting = new PasswordSetting(userPassword, ownerPassword);
                PDFDocument.AddPassword(outputFilePath, setting);
            }
        }

        #endregion

        #region Utility to create PDF optimize option object from controls' input.

        //  Get optimize option object from the controls.
        private PDFOptimizeOptions getOptimizeOptions()
        {
            PDFOptimizeOptions ops = new PDFOptimizeOptions();
            //  Enable images optimization
            ops.EnableImagesOptimization = true;
            //  For color images
            ops.ColorImageOptions.DownsampleMode = getDownSample(this.ColorDownsampleMode.Text);
            ops.ColorImageOptions.TargetResolution = getResolution(this.ColorTargetPPI.Text);
            ops.ColorImageOptions.MaxResolutionLimit = getResolution(this.ColorMaximumPPI.Text);
            ops.ColorImageOptions.Compression = getCompression(this.ColorCompression.Text);
            ops.ColorImageOptions.JPEGImageQualityLevel = getQualityLevel(this.ColorJPEGQuality.Text);
            //  For grayscale images
            ops.GrayscaleImageOptions.DownsampleMode = getDownSample(this.GrayDownsampleMode.Text);
            ops.GrayscaleImageOptions.TargetResolution = getResolution(this.GrayDownsampleMode.Text);
            ops.GrayscaleImageOptions.MaxResolutionLimit = getResolution(this.GrayDownsampleMode.Text);
            ops.GrayscaleImageOptions.Compression = getCompression(this.GrayDownsampleMode.Text);
            ops.GrayscaleImageOptions.JPEGImageQualityLevel = getQualityLevel(this.GrayDownsampleMode.Text);
            //  For monochrome images
            ops.MonochromeImageOptions.DownsampleMode = getDownSample(this.MonoDownsampleMode.Text);
            ops.MonochromeImageOptions.TargetResolution = getResolution(this.MonoTargetPPI.Text);
            ops.MonochromeImageOptions.MaxResolutionLimit = getResolution(this.MonoMaximumPPI.Text);
            ops.MonochromeImageOptions.Compression = getCompression(this.MonoCompression.Text);

            return ops;
        }

        //  Valid Input: a string for positive float value.
        private float getResolution(string ppi)
        {
            try
            {
                return float.Parse(ppi);
            }
            catch (Exception)
            {
                //  Return default resolution value if input is invalid.
                return 96F;
            }
        }

        //  Valid Input:
        //  "Off", "Average Downsampling to", "Subsampling to", "Bicubic Downsampling to"
        private ImageDownsampleMode getDownSample(string downSample)
        {
            ImageDownsampleMode result = ImageDownsampleMode.None;
            if (downSample == "Bicubic Downsampling to")
                result = ImageDownsampleMode.Bicubic;
            else if (downSample == "Average DownSampling to")
                result = ImageDownsampleMode.Bilinear;
            else if (downSample == "Subsampling to")
                result = ImageDownsampleMode.NearestNeighbor;
            return result;
        }

        //  Valid Input:
        //  "ASCII85", "ASCIIHex", "CCITTFax", "DCT", "Flate"
        //  "JBIG2", "JPX", "LZW", "NoFilter, "RunLength"
        private PDFCompression getCompression(string compression)
        {
            PDFCompression result = PDFCompression.NoFilter;
            if (compression == "ASCII85")
                result = PDFCompression.ASCII85Decode;
            else if (compression == "ASCIIHex")
                result = PDFCompression.ASCIIHexDecode;
            else if (compression == "CCITTFax")
                result = PDFCompression.CCITTFaxDecode;
            else if (compression == "DCT")
                result = PDFCompression.DCTDecode;
            else if (compression == "Flate")
                result = PDFCompression.FlateDecode;
            else if (compression == "JBIG2")
                result = PDFCompression.JBIG2Decode;
            else if (compression == "JPX")
                result = PDFCompression.JPXDecode;
            else if (compression == "LZW")
                result = PDFCompression.LZWDecode;
            else if (compression == "RunLength")
                result = PDFCompression.RunLengthDecode;
            return result;
        }

        //  Valid Input: "Minimum", "Low", "Medium", "High", "Maximum"
        private JPEGImageQualityLevel getQualityLevel(string qualityLevel)
        {
            JPEGImageQualityLevel level = JPEGImageQualityLevel.Lowest;
            if (qualityLevel == "Low")
                level = JPEGImageQualityLevel.Low;
            else if (qualityLevel == "Medium")
                level = JPEGImageQualityLevel.Medium;
            else if (qualityLevel == "High")
                level = JPEGImageQualityLevel.High;
            else if (qualityLevel == "Maximum")
                level = JPEGImageQualityLevel.Highest;
            return level;
        }

        #endregion
    }
}




Conclusion

Now you have created a WPF Windows application with PDF compress and password protection applied using C#. With XDoc.PDF C# library, you are able to add more PDF features such as conversion, editing, generating and printing in your C# WPF application.