为单个平台创建缺少的自定义渲染器

时间:2019-11-28 10:36:54

标签: xamarin xamarin.forms

我需要使用某些库中的PdfViewer。该库为Android,IOS,UWP平台提供控件,但不为WPF平台提供控件。如何仅为WPF平台创建渲染器?

WPF渲染器:

[assembly: ExportRenderer(typeof(PdfViewer), typeof(PdfViewerRenderer))]
public class PdfViewerRenderer : Xamarin.Forms.Platform.WPF.ViewRenderer<PdfViewer, WPF.PlatformImplementations.PdfViewer>{}

WPF控件的实现:

namespace WPF.PlatformImplementations
{ public class PdfViewer : PdfViewerControl { } }

Net标准库包含PdfViewer,它是从SfPdfViewer的库中派生的:

namespace Views
{ public class PdfViewer : SfPdfViewer { } }

以上方法不适用于WPF,不适用于其他平台。当我将继承从SfPdfViewer更改为Xamarin.Forms.View时,它适用于WPF,但显然不适用于其他平台。

2 个答案:

答案 0 :(得分:3)

每个Xamarin.Forms控件都有一个随附的渲染器,用于每个需要创建本机控件实例的平台。

SfPdfViewer是一个xamarin形式的控件,仅表示共享的UI状态和交互逻辑。它需要一个相应的本机控件来实际呈现视图并与WPF平台进行交互。

为此,第一步是选择一个基于WPF的控件来查看PDF文件。在此示例中,我使用了WPF Pdf Viewer by SyncFusion;但任何其他选项-可能像嵌入式WebView或开源选项如PdfiumViewer也应起作用。

步骤1:

在WPF项目中为Syncfusion.PdfViewer.WPF安装nuget程序包

步骤2:

使用平台渲染器,将带有表单元素(SfPdfViewer)与本机控件(PdfViewerControl)相连。

[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();
            }
        }
    }
}

参考示例项目已上传到Github

Demo

答案 1 :(得分:0)

一种实现方法是在Core项目中创建一个CustomPdfViewer接口,并使用依赖注入在每个本机项目中具有单独的实现。

在每个iOS,Android和UWP项目的本机实现中,只需使其使用适用于您的PdfViewer库即可。

然后对于WPF,只需使用SfPdfViewer

例如:您可以通过示例查看DependencyService上的official documentation here

执行此操作后,您将拥有解决方案。但是,如果您想更进一步并访问在XAML中创建的CustomPdfViewer,则可以使用由术语local表示的“ XAML Markup Extensions”,如示例中所示here