I need to use PdfViewer from some library. This library provides control for Android, IOS, UWP platforms but not for WPF platform. How to create a renderer only for WPF platform?
WPF renderer:
[assembly: ExportRenderer(typeof(PdfViewer), typeof(PdfViewerRenderer))]
public class PdfViewerRenderer : Xamarin.Forms.Platform.WPF.ViewRenderer<PdfViewer, WPF.PlatformImplementations.PdfViewer>
{
}
WPF control implementation:
namespace WPF.PlatformImplementations
{
public class PdfViewer
{
//custom implementation of pdf viewer for wpf
}
}
Net standard library contains PdfViewer which derives from SfPdfViewer from a library:
namespace Views
{
public class PdfViewer : SfPdfViewer
{
//implementation of pdf viewer using base class from multiplatform library
}
}
The above approach does not work for WPF and works for other platforms. When I change inheritance from SfPdfViewer to Xamarin.Forms.View then it works for WPF but obviously does not work for other platforms. So the problem is to make renderer mechanizm to recognize Views.PdfViewer as control based on Xamarin.Forms.View.
Every Xamarin.Forms control has a accompanying renderer for each platform that needs to create an instance of a native control.
SfPdfViewer is a xamarin-forms control that only represents the shared UI state, and interaction logic. It needs a corresponding native control to actually render the view and interact with WPF platform.
In order to do that, first step would be to choose a WPF based control for viewing PDF files. For this example I have used WPF Pdf Viewer by SyncFusion; but any other option - probably like an embedded WebView or an open-source option like PdfiumViewer should also work.
Install nuget package for Syncfusion.PdfViewer.WPF in WPF project
Wire up the with forms-element (SfPdfViewer) with native-control (PdfViewerControl) using platform renderer.
[assembly: ExportRenderer(typeof(SfPdfViewer), typeof(SfPdfViewerRenderer))]
namespace PdfViewer.Demo.WPF
{
public class SfPdfViewerRenderer
: ViewRenderer<SfPdfViewer, Syncfusion.Windows.PdfViewer.PdfViewerControl>
{
Syncfusion.Windows.PdfViewer.PdfViewerControl _nativeControl;
protected override void OnElementChanged(ElementChangedEventArgs<SfPdfViewer> e)
{
base.OnElementChanged(e);
// If new forms element attached, wire up the native control
if (e.NewElement != null)
{
_nativeControl = new Syncfusion.Windows.PdfViewer.PdfViewerControl();
SetNativeControl(_nativeControl);
}
// Otherwise perform some cleanup
else
{
if(_nativeControl != null)
{
_nativeControl.Unload();
_nativeControl = null;
}
}
UpdateNativeControlProperties();
}
/// <summary>
/// Basically sync property values from forms-element (SfPdfViewer)
/// to native-control (PdfViewerControl)
/// In this example - we only sync with 'input file stream'
/// </summary>
private void UpdateNativeControlProperties()
{
if (Element != null && Element.InputFileStream != null)
{
Control.Load(Element.InputFileStream);
}
else
{
Control.Unload();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(SfPdfViewer.InputFileStream))
{
UpdateNativeControlProperties();
}
}
}
}

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With