This is a migrated thread and some comments may be shown as answers.

Binding PDFViewer to MVVM Byte Array

3 Answers 530 Views
PDFViewer
This is a migrated thread and some comments may be shown as answers.
Sandra
Top achievements
Rank 1
Sandra asked on 04 Jul 2018, 02:26 PM

I'm trying to using MVVM binding for the pdfviewer but the document always turns out blank.  I'm querying a DB field that contains the bytes of the PDF file and I'm trying to get it to display in the viewer (I've confirmed that the file is not malformed and it displays fine if I save it as a PDF to my desktop).

Here are my MVVM properties:

private RadFixedDocument _currentDocument;
public RadFixedDocument CurrentDocument
{
    get => _currentDocument; set => this.RaiseAndSetIfChanged(ref _currentDocument, value);
}

 

Here is the method I'm using to populate the CurrentDocument property:

var sqlStr = @"select top 1 * from FileManager order by ID desc;";
var file = await con.QuerySingleAsync<FMFile>(sqlStr);
var fileBytes = file.FileContent.ToArray();  // this is type byte[] - I confirmed that it has the correct contents
var ms = new MemoryStream(fileBytes); // ms gets filled properly
FormatProviderSettings settings = new FormatProviderSettings(ReadingMode.AllAtOnce);
PdfFormatProvider provider = new PdfFormatProvider(ms, settings);
CurrentDocument = provider.Import();

 

And here is how my XAML looks:

<telerik:RadPdfViewerToolBar RadPdfViewer="{Binding ElementName=pdfViewer, Mode=OneTime}" />
<telerik:RadPdfViewer x:Name="pdfViewer"
                              Grid.Row="1"
                              DocumentSource="{Binding CurrentDocument, Mode=TwoWay}" />

 

However, nothing get's displayed in the viewer.  I confirmed that my VM is hooked up correctly as other property display just fine.  Any advice would be appreciated.

3 Answers, 1 is accepted

Sort by
0
Georgi
Telerik team
answered on 05 Jul 2018, 03:29 PM
Hi Sandra,

You can bind the DocumentSource property of RadPdfViewer to a URI, string representing a URI or a stream (but not to RadFixedDocument instance directly) using the PdfDocumentSourceValueConverter as can be seen in the Binding the DocumentSource of RadPdfViewer section of the documentation. For example:
<Window x:Class="FixedDocumentViewerDemoWpf.MainWindow"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             xmlns:fixed="clr-namespace:Telerik.Windows.Documents.Fixed;assembly=Telerik.Windows.Controls.FixedDocumentViewers"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
  
    <Grid.Resources>
        <fixed:PdfDocumentSourceValueConverter x:Key="PdfDocumentSourceValueConverter" />
    </Grid.Resources>
  
    <telerik:RadPdfViewerToolBar RadPdfViewer="{Binding ElementName=pdfViewer, Mode=OneTime}" />
    <telerik:RadPdfViewer x:Name="pdfViewer"
                              Grid.Row="1"
                              DocumentSource="{Binding Path=ViewModel.CurrentDocument, Mode=TwoWay, Converter={StaticResource
                              PdfDocumentSourceValueConverter}}" />
</Window>

I hope this helps.

Regards,
Georgi
Progress Telerik
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 you to write beautiful native mobile apps using a single shared C# codebase.
0
Sandra
Top achievements
Rank 1
answered on 05 Jul 2018, 08:57 PM

Hi Georgi,

 

Ok, when I change my property to be a Stream instead, an exception gets thrown that looks like its from one of the Telerik DLL's possibly.  I checked that my 'mStream' variable (which you'll see below) does have the bytes in it that it needs.  Here's the output:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Telerik.Windows.Controls.FixedDocumentViewers
  StackTrace:
   at Telerik.Windows.Documents.Fixed.FixedDocumentStreamSource.ExecuteLoadAction(Action action)
   at Telerik.Windows.Documents.Fixed.FixedDocumentStreamSource.<>c__DisplayClass8.<LoadDocument>b__6()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

 

And here's how I changed my code:

private Stream _currentDocument;
public Stream CurrentDocument
{
  get => _currentDocument; set => this.RaiseAndSetIfChanged(ref _currentDocument, value);

}

 

And my populate function:

private void LoadFile()
        {
            using (var con = _mb.sqlHelper.OpenSysproDbConnection())
            {
                var sqlStr = @"select top 1 * from FileManager order by ID desc;";
                var file = con.QuerySingle<FMFile>(sqlStr);
                var fileBytes = file.FileContent.ToArray();
                MemoryStream mStream = new MemoryStream(fileBytes);
                CurrentDocument = mStream;
            }
        }

 

As for my view, I'm using the same code that you have there for the converter.

0
Accepted
Georgi
Telerik team
answered on 10 Jul 2018, 03:01 PM
Hello Sandra,

I've investigated the code in FixedDocumentStreamSource.ExecuteLoadAction, and it seems that the NullReferenceException is thrown because the WPF's Application.Current property is still null. The following could cause such issue:
  1. The DocumentSource property is bound before the WPF's Application instance has been created (it's typically created in the automatically generated Main method in the WPF application assembly).
  2. The view containing the RadPdfViewer is used in a non-WPF application, so the Application instance is never set.

Possible workaround would be to set an Application.Current instance before the document is actually loaded and observe if the exception still occurs. This could be achieved by just creating an Application instance somewhere before the problematic code:
new System.Windows.Application();

Note that you don't have to set the created instance anywhere, it will automatically set itself to the Application.Current property.

I hope this helps.

Regards,
Georgi
Progress Telerik
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.
Tags
PDFViewer
Asked by
Sandra
Top achievements
Rank 1
Answers by
Georgi
Telerik team
Sandra
Top achievements
Rank 1
Share this question
or