ExportPDF Custom Command Descriptor Issue

7 posts, 0 answers
  1. Brandon
    Brandon avatar
    5 posts
    Member since:
    Jan 2017

    Posted 24 Jan Link to this post

    Hello,

    I have written a Custom Command Descriptor based on the Telerik demos and documentation that exports the currently loaded document to a local file. Everything appears to be working 100% correct with no errors. However, when I open the file all the pages are blank. The page count is correct, so it appears to be reading the PDFViewer document correctly into the stream, just not writing all of the bytes properly. Here is my code behind for the page that contains the Document Viewer control.

     

    using System;
    using System.IO;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using Telerik.Windows.Documents.Fixed.FormatProviders;
    using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf;
    using Telerik.Windows.Documents.Fixed.Model;
    using WeldTrackingWPF.ViewModel;
    using Telerik.Windows.Controls;
    using Telerik.Windows.Documents.Commands.Descriptors;
    using Telerik.Windows.Documents.Commands;
     
    namespace WeldTrackingWPF.View
    {
        /// <summary>
        /// Interaction logic for ViewQualificationDoc.xaml
        /// </summary>
        public partial class ViewDoc : Page
        {
            public ViewDoc(byte[] fileBytes)
            {
     
                InitializeComponent();
     
                /// <summary>
                ///  Read bytes into memory stream
                ///  Pass stream in RadPdfViewer for viewing
                /// </summary>
     
     
                this.pdfViewer.CommandDescriptors = new CustomCommandDescriptors(this.pdfViewer);
     
                Stream stream = new MemoryStream(fileBytes);
     
                FormatProviderSettings settings = new FormatProviderSettings(ReadingMode.AllAtOnce);
     
                PdfFormatProvider provider = new PdfFormatProvider(stream, settings);
     
                RadFixedDocument doc = provider.Import();
     
                this.pdfViewer.Document = doc;
     
                IconSources.ChangeIconsSet(IconsSet.Modern);
     
     
     
            }
     
            private void Page_Initialized(object sender, EventArgs e)
            {
                var vm = new ViewDocViewModel();
                DataContext = vm;
            }
     
            private void PdfViewer_DocumentLoaded(object sender, EventArgs args)
            {
            }
     
            private void Page_Unloaded(object sender, RoutedEventArgs e)
            {             
            }
     
            private void tbCurrentPage_KeyDown(object sender, KeyEventArgs e)
            {
                TextBox textBox = sender as TextBox;
                if (textBox != null)
                {
                    if (e.Key == System.Windows.Input.Key.Enter)
                    {
                        textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
                    }
                }
            }
        }
     
        public class SaveCommand : FixedDocumentViewerCommandBase
        {
            public SaveCommand(FixedDocumentViewerBase fixedDocumentViewerBase)
                : base(fixedDocumentViewerBase)
            {
            }
     
            public override void Execute(object parameter)
            {
                Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
                dialog.Filter = "PDF files (*.pdf)|*.pdf";
     
                bool? result = dialog.ShowDialog();
     
                if (result.HasValue && result.Value)
                {
     
                    using (Stream stream = File.OpenWrite(dialog.FileName))
                    {
     
                        PdfFormatProvider provider = new PdfFormatProvider();
                        provider.Export(this.Viewer.Document, stream);
     
                    }
                }
            }
        }
     
        public class CustomCommandDescriptors : DefaultCommandDescriptors
        {
            private readonly CommandDescriptor saveCommandDescriptor;
     
            public CommandDescriptor SaveCommandDescriptor
            {
                get
                {
                    return this.saveCommandDescriptor;
                }
            }
     
            public CustomCommandDescriptors(FixedDocumentViewerBase fixedDocumentViewer) : base(fixedDocumentViewer)
            {
                this.saveCommandDescriptor = new CommandDescriptor(new SaveCommand(fixedDocumentViewer));
            }
        }
     
    }

    Any insight as to why these documents are being exported sans page content would be appreciated.

     

    Thanks!

  2. Tanya
    Admin
    Tanya avatar
    577 posts

    Posted 26 Jan Link to this post

    Hi Brandon,

    I checked the code you shared and noticed that the wrong provider is used to export the document of RadPdfViewer.

    The PdfFormatProvider class is shared between RadPdfViewer and RadPdfProcessing and, depending on the constructor you are using, a provider instance for the different control is created. To be more precise, to create a provider to work with in RadPdfViewer, you should use the constructor that takes two parameters, as shown in Example 5 of the Showing a File article. The default constructor will create a PdfFormatProvider instance which is working with the model of RadPdfProcessing. 

    Here is how I modified a part of the code you shared to use the PdfFormatProvider for PdfViewer:
    public override void Execute(object parameter)
    {
        Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
        dialog.Filter = "PDF files (*.pdf)|*.pdf";
     
        bool? result = dialog.ShowDialog();
     
        if (result.HasValue && result.Value)
        {
     
            using (Stream stream = File.OpenWrite(dialog.FileName))
            {
     
                PdfFormatProvider provider = new PdfFormatProvider(stream, FormatProviderSettings.ReadOnDemand);
                provider.Export(this.Viewer.Document, stream);
     
            }
        }
    }

    Hope this helps.

    Regards,
    Tanya
    Telerik by Progress
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  3. Brandon
    Brandon avatar
    5 posts
    Member since:
    Jan 2017

    Posted 26 Jan in reply to Tanya Link to this post

    This results in the following error:

    The stream type is not supported.

    I assume that when using this Overload, the PdfFormatProvider is attempting to read the stream, which is not allowed on a FileStream created using File.OpenWrite. 

  4. Brandon
    Brandon avatar
    5 posts
    Member since:
    Jan 2017

    Posted 26 Jan in reply to Brandon Link to this post

    I believe that I overcame the above error by using dialog.OpenFile(), however now I am getting a NotSupportExecption stating the following:

    An unhandled exception of type 'System.NotSupportedException' occurred in Telerik.Windows.Documents.Fixed.dll

    Additional information: This method is only supported when initializing PdfFormatProvider through the PdfFormatProvider() constructor.

    using (Stream stream = dialog.OpenFile())
    {
     
        PdfFormatProvider provider = new PdfFormatProvider(stream, FormatProviderSettings.ReadOnDemand);
        provider.Export(this.Viewer.Document, stream);
     
    }

     

     

  5. Tanya
    Admin
    Tanya avatar
    577 posts

    Posted 26 Jan Link to this post

    Hi Brandon,

    I have misunderstood your initial inquiry. Please, accept my apologies for misleading you.

    RadPdfViewer doesn't support exporting the loaded document out-of-the-box. We have already logged a request to implement this functionality and you can submit your vote as well as track the progress of the task using the related public item.

    At this point, I can suggest you check the Custom Save Command example in our SDK repository. The sample shows how you can customize the Open command in order to preserve the document stream and use it later in the Save command to export.

    I hope this is helpful.

    Regards,
    Tanya
    Telerik by Progress
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
  6. Brandon
    Brandon avatar
    5 posts
    Member since:
    Jan 2017

    Posted 26 Jan in reply to Tanya Link to this post

    Currently, we are not loading documents through the OpenCommand on the viewer, they are loaded from the code behind after the document is retrieved from the database. For now, we have a work around in place where the byte[] array is stored in the page object, obviously not ideal, and used later to build the save stream.

    This seems like a major oversight and it's very disappointing that this functionality is not offered out of the box.

  7. Tanya
    Admin
    Tanya avatar
    577 posts

    Posted 31 Jan Link to this post

    Hello Brandon,

    RadPdfViewer currently doesn't expose a way to save the document stream to a file. Therefore, the stream should be preserved internally and the approach you are using is pretty similar to the one demonstrated in the example - the stream is preserved in a variable when loading a document so it can be saved later.

    If you would like, you can increase the priority of the task by voting for its implementation through the feedback item I linked in my previous reply.

    Regards,
    Tanya
    Telerik by Progress
    Want to extend the target reach of your WPF applications, leveraging iOS, Android, and UWP? Try UI for Xamarin, a suite of polished and feature-rich components for the Xamarin framework, which allow you to write beautiful native mobile apps using a single shared C# codebase.
Back to Top