在WPF应用程序中显示PDF不起作用 - WebBrowser或Adobe控件

4

我需要在WPF应用程序中显示PDF文档。根据我在网上阅读的所有资料,似乎在WPF应用程序中显示PDF的唯一方法是通过Adobe的控件或WebBrowser控件。我尝试使用Adobe的控件,但是由于某种原因,我无法将Reader控件添加到工具箱中(即使添加了所需的引用)。我正在运行Windows 7(64位),VS2010,.NET 4.0,并安装了Adobe Acrobat 7.0 Professional和Adobe Acrobat 9 Pro Extended,如果有关系的话。所以,我决定在WindowsFormsHost中托管的WebBrowser控件中尝试它。我拥有的XAML如下:

<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>

接下来是C#代码:

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

其中的FileName应该是我需要显示的.pdf文件的确切位置。然而,当我运行这个程序时,我只看到一个完全空白的区域,WebBrowser也没有显示出来。我也尝试过像这样设置.pdf文件:

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

我尝试了同样的步骤,但是得到了完全相同的结果。我知道PDF文件已经创建在正确的位置,因为我可以手动浏览并正常打开它。

有人有任何想法为什么这不起作用吗?或者可能为什么我似乎没有阅读器控件作为选项?此时,任一解决方案都可以,只要它们中的任何一个能够起作用!

谢谢!


你好,如果我没记错的话,你需要创建一个WinForms用户控件,并在其中使用Adobe的控件来查看PDF文件。然后,你可以使用<WinFormsHost>标签将用户控件插入到你的XAML中。 - LD7
问题是我一直没有能够看到Adobe控件,即使添加了正确的Acrobat引用,然后转到工具箱->选择项->COM组件。阅读器控件就是不在那里,所以我无法在用户控件上使用它。我不知道为什么它不显示为选项:( - JToland
3个回答

7
以下是我所做的事情...
主窗口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>

主窗口后台代码

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;
        }

    }
}

不错,但你可能想解释一下你做了什么。例如,这会读取 PDF 中的字节,然后使用 HttpListenerResponse 将字节流传输到浏览器中。 - Conrad Frix

0

我以前确实遵循过这个步骤。但是,我遇到的问题是,在我尝试将Adobe控件添加到我的工具箱时,如他在视频中所解释的那样,该控件并不是一个选项。我只有“Acrobat 3D Office Insert”和“Adobe Acrobat 7.0 Browser Control”。这些是用于此目的的控件的“新”名称吗?在那篇文章中,他使用了一个我没有的“Reader”控件... - JToland
你尝试过那个“浏览器控件”吗?它看起来就是你需要的。 - hectorct
与现在一起工作。尝试像参考链接使用读取器控件一样使用它会导致我遇到“跨线程操作”异常,指示我从创建它的线程以外的线程访问了该控件... - JToland

0
晚回答了,但可能会对其他人有所帮助。
我正在使用Windows 8.1 x64机器工作。
我的任务是使用户能够在设备上查看PDF文档(带有Windows操作系统的平板电脑)。经过大量研究,我找不到任何可行的解决方案,或者我应该说使用WindowsFormsHost感觉很肮脏!

我所做的是使用WebBrowser控件,如下所示:

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

注意: pack://siteoforigin: 是指应用程序运行时的位置。因此,请确保您的 .html 文件设置为 ContentCopy Always。 现在,您已经设置好了 HTML,需要下载或者复制粘贴以下的 .js 代码:
/*
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;
};

这是从GitHub存储库中使用的
现在,一旦您设置好了,您需要安装Adobe Reader
您的html页面应该像这样(用于测试):

<!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>

现在是棘手的部分。
如果成功,您需要让这个html页面在您的WebBrowser控件中显示,然后会提示您安装Adobe Acrobat Reader的更新。
更新成功后,请重新启动应用程序,您的文件现在应该出现在您的页面上!
编码愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接