4
votes

I need to display a PDF in a WPF application. From all the reading I've been doing online, it seems the [only?] ways of displaying a PDF within a WPF application is via Adobe's controls or a WebBrowser control. I've tried to use Adobe's controls, however, I have been unable to add the Reader control because for some reason I can't find the it as something I can add into my Toolbox (even once adding the reference needed). I'm running Windows 7 (64-bit), VS2010, .NET 4.0, and have Adobe Acrobat 7.0 Professional and Adobe Acrobat 9 Pro Extended installed, if that has anything to do with it. So anyway, I decided to try it in a WebBrowser control hosted in a WindowsFormsHost. The XAML I have is this:

<WindowsFormsHost x:Name="FormsHost" Visibility="Visible" Grid.Column="1" Margin="7,0,0,0">
<WF:WebBrowser x:Name="WebBrowser" Dock="Fill" IsWebBrowserContextMenuEnabled="False" ScriptErrorsSuppressed="True" WebBrowserShortcutsEnabled="False" Margin="7,0,0,0" />
</WindowsFormsHost>

and then this in the C# code behind:

WebBrowser.Navigate(new System.Uri(FileName));

where FileName == the exact location of the .pdf file I need to display. However, when I run this all I see is a completely blank, white area where the WebBrowser is. I've also tried setting the .pdf file like this:

WebBrowser.Url = new System.Uri(FileName);

and I get the exact same thing. I know the PDF is being created in the correct location, as I can manually browse to it and open it fine.

Does anyone have any ideas as to why this isn't working? Or possibly why I don't seem to have the Reader control as an option? At this point, either solution would be fine, they just neither one seem to be working!

Thanks!

3
Hi, if I remember correctly you have to create a winforms user control and in it use adobe's control to view pdfs. Then you use the <WinFormsHost> tag to insert the user control in your xaml.LD7
The problem is that I've not been able to see the Adobe control, even when adding the correct Acrobat reference and then going to Toolbox -> Choose Items -> COM Components. The Reader control just isn't there, so I can't use it on a user control. I have no idea's as to why it doesn't show up as an option :(JToland

3 Answers

7
votes

Here is what I did...

MAIN WINDOW XAML

 <Window x:Class="PDFView.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="PDFView">
        <Grid>
            <WebBrowser x:Name="Browser" />
        </Grid>
    </Window>

MAIN WINDOW CODE BEHIND

using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Navigation;

namespace PDFView {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string hostUri = "http://localhost:8088/PsuedoWebHost/";

        private HttpListener _httpListener;

        public MainWindow() {
            InitializeComponent();

            this.Loaded += OnLoaded;
        }

        /// <summary>
        /// Loads the specified PDF in the WebBrowser control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="routedEventArgs"></param>
        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            // Get the PDF from the 'database'
            byte[] pdfBytes = GetPdfData();

            // Create a PDF server that serves the PDF to a browser
            CreatePdfServer(pdfBytes);

            // Cleanup after the browser finishes navigating
            Browser.Navigated += BrowserOnNavigated;
            Browser.Navigate(hostUri);
        }

        /// <summary>
        /// Retrieve a byte array from a 'database record'
        /// </summary>
        /// <returns></returns>
        private byte[] GetPdfData() {
            // TODO: Replace this code with data access code
            // TODO: Pick a file from the file system for this demo.
            string path = @"c:\Users\Me\Documents\MyPDFDocument.pdf"; 
            byte[] pdfBytes = File.ReadAllBytes(path);

            // Return the raw data
            return pdfBytes;
        }

        /// <summary>
        /// Creates an HTTP server that will return the PDF  
        /// </summary>
        /// <param name="pdfBytes"></param>
        private void CreatePdfServer(byte[] pdfBytes) {
            _httpListener = new HttpListener();
            _httpListener.Prefixes.Add(hostUri);
            _httpListener.Start();
            _httpListener.BeginGetContext((ar) => {
                                                  HttpListenerContext context = _httpListener.EndGetContext(ar);

                                                  // Obtain a response object.
                                                  HttpListenerResponse response = context.Response;
                                                  response.StatusCode = (int)HttpStatusCode.OK;
                                                  response.ContentType = "application/pdf";

                                                  // Construct a response.
                                                  if (pdfBytes != null) {
                                                      response.ContentLength64 = pdfBytes.Length;

                                                      // Get a response stream and write the PDF to it.
                                                      Stream oStream = response.OutputStream;
                                                      oStream.Write(pdfBytes, 0, pdfBytes.Length);
                                                      oStream.Flush();
                                                  }

                                                  response.Close();
                                              }, null);

        }

        /// <summary>
        /// Stops the http listener after the browser has finished loading the document
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="navigationEventArgs"></param>
        private void BrowserOnNavigated(object sender, NavigationEventArgs navigationEventArgs)
        {
            _httpListener.Stop();
            Browser.Navigated -= BrowserOnNavigated;
        }

    }
}
0
votes

I'm afraid you are stuck using the WinForms PDF control and hosting it in your WPF application. Its a little annoying, but its not difficult to do. Here is an article and some sample source code:

http://hugeonion.com/2009/04/06/displaying-a-pdf-file-within-a-wpf-application/

0
votes

Late answer but it might help other people.
I am working on a Windows 8.1 x64 machine.
My task was to enable users to view PDF documents on the device (Tablet with Windows OS). After much of a research I couldn't find any feasible solution, or what I should say using WindowsFormsHost just feels dirty!

What I have done is to use a WebBrowser control like so:

<WebBrowser Source="pack://siteoforigin:,,,/path/to/your/file.html"/>

Note: The pack://siteoforigin: refers to a location when your application is running. So make sure your .html files are set to Content and Copy Always.
Now that your html has been set up you need to now either download or just copy and paste the following .js code:

/*
PDFObject v1.2.20111123
https://github.com/pipwerks/PDFObject
Copyright (c) Philip Hutchison
MIT-style license: http://pipwerks.mit-license.org/
*/
/*jslint browser: true, sloppy: true, white: true, plusplus: true */
/*global ActiveXObject, window */
var PDFObject = function (obj) {

if (!obj || !obj.url) { return false; }

var pdfobjectversion = "1.2",
    //Set reasonable defaults
    id = obj.id || false,
    width = obj.width || "100%",
    height = obj.height || "100%",
    pdfOpenParams = obj.pdfOpenParams,
    url,
    pluginTypeFound,

    //declare functions
    createAXO,
    hasReaderActiveX,
    hasReader,
    hasGeneric,
    pluginFound,
    setCssForFullWindowPdf,
    buildQueryString,
    get,
    embed;


/* ----------------------------------------------------
   Supporting functions
   ---------------------------------------------------- */

createAXO = function (type) {
    var ax;
    try {
        ax = new ActiveXObject(type);
    } catch (e) {
        //ensure ax remains null
        ax = null;
    }
    return ax;
};

//Tests specifically for Adobe Reader (aka Acrobat) in Internet Explorer
hasReaderActiveX = function () {

    var axObj = null;

    if (window.ActiveXObject) {

        axObj = createAXO("AcroPDF.PDF");

        //If "AcroPDF.PDF" didn't work, try "PDF.PdfCtrl"
        if (!axObj) { axObj = createAXO("PDF.PdfCtrl"); }

        //If either "AcroPDF.PDF" or "PDF.PdfCtrl" are found, return true
        if (axObj !== null) { return true; }

    }

    //If you got to this point, there's no ActiveXObject for PDFs
    return false;

};



//Tests specifically for Adobe Reader (aka Adobe Acrobat) in non-IE browsers
hasReader = function () {

    var i,
        n = navigator.plugins,
        count = n.length,
        regx = /Adobe Reader|Adobe PDF|Acrobat/gi;

    for (i = 0; i < count; i++) {
        if (regx.test(n[i].name)) {
            return true;
        }
    }

    return false;

};


//Detects unbranded PDF support
hasGeneric = function () {
    var plugin = navigator.mimeTypes["application/pdf"];
    return (plugin && plugin.enabledPlugin);
};


//Determines what kind of PDF support is available: Adobe or generic
pluginFound = function () {

    var type = null;

    if (hasReader() || hasReaderActiveX()) {

        type = "Adobe";

    } else if (hasGeneric()) {

        type = "generic";

    }

    return type;

};


//If setting PDF to fill page, need to handle some CSS first
setCssForFullWindowPdf = function () {

    var html = document.getElementsByTagName("html"),
        html_style,
        body_style;

    if (!html) { return false; }

    html_style = html[0].style;
    body_style = document.body.style;

    html_style.height = "100%";
    html_style.overflow = "hidden";
    body_style.margin = "0";
    body_style.padding = "0";
    body_style.height = "100%";
    body_style.overflow = "hidden";

};


//Creating a querystring for using PDF Open parameters when embedding PDF
buildQueryString = function (pdfParams) {

    var string = "",
        prop;

    if (!pdfParams) { return string; }

    for (prop in pdfParams) {

        if (pdfParams.hasOwnProperty(prop)) {

            string += prop + "=";

            if (prop === "search") {

                string += encodeURI(pdfParams[prop]);

            } else {

                string += pdfParams[prop];

            }

            string += "&";

        }

    }

    //Remove last ampersand
    return string.slice(0, string.length - 1);

};


//Simple function for returning values from PDFObject
get = function (prop) {

    var value = null;

    switch (prop) {
        case "url": value = url; break;
        case "id": value = id; break;
        case "width": value = width; break;
        case "height": value = height; break;
        case "pdfOpenParams": value = pdfOpenParams; break;
        case "pluginTypeFound": value = pluginTypeFound; break;
        case "pdfobjectversion": value = pdfobjectversion; break;
    }

    return value;

};


/* ----------------------------------------------------
   PDF Embedding functions
   ---------------------------------------------------- */


embed = function (targetID) {

    if (!pluginTypeFound) { return false; }

    var targetNode = null;

    if (targetID) {

        //Allow users to pass an element OR an element's ID
        targetNode = (targetID.nodeType && targetID.nodeType === 1) ? targetID : document.getElementById(targetID);

        //Ensure target element is found in document before continuing
        if (!targetNode) { return false; }

    } else {

        targetNode = document.body;
        setCssForFullWindowPdf();
        width = "100%";
        height = "100%";

    }

    targetNode.innerHTML = '<object    data="' + url + '" type="application/pdf" width="' + width + '" height="' + height + '"></object>';

    return targetNode.getElementsByTagName("object")[0];

};

//The hash (#) prevents odd behavior in Windows
//Append optional Adobe params for opening document
url = encodeURI(obj.url) + "#" + buildQueryString(pdfOpenParams);
pluginTypeFound = pluginFound();

this.get = function (prop) { return get(prop); };
this.embed = function (id) { return embed(id); };
this.pdfobjectversion = pdfobjectversion;

return this;
};

Which has been used from gihub repository
Now once you have that set up you need now to install Adobe Reader
Your html page should look like this (for testing):

<!DOCTYPE html>
<!-- saved from url=(0016)http://localhost -->
<head>
<title></title>
<link rel="javascript" href="js/pdfObject.js" />
</head>
<body style="border: 0; margin: 0; padding: 0">
    <embed src="..\path\to\your\file.pdf" width="600px" height="500px" alt="pdf" pluginspage="http://www.adobe.com/products/acrobat/readstep2.html">
</body>

Now the tricky part.
You need to get this html page to display in your WebBrowser control, if successful you will be prompted to install an update for your acrobat reader.
After the update has been successful restart the application and your file should now appear on your page!
Happy coding!