如何在DependencyService中访问本机控件?

时间:2016-04-20 07:47:39

标签: xamarin xamarin.forms

我有多个基于平台的依赖服务,它们充当绑定项目的接口(代码而不是UI),而这些项目反过来“可以”产生对模态视图控制器的切换,并且他们需要附加哪个视图。

实现依赖接口后:

public interface IProcessAndRespond
{
    void gpuCalc (Byte[] data, object view);
}

在平台代码中,我需要将Android Context / Widget / View,iOS UIView和/或UIViewController传递给各种平台规范例程。

public class DateTimeDialog_iOS : IDateTimeDialog
{
    public DateTimeDialog_iOS ()
    {
    }
    void gpuCalc (Byte[] data, object view)
    {
       // lookup a native control by name? id? 
    }
}

如何在我的gpuCalc方法中引用本机控件?

1 个答案:

答案 0 :(得分:2)

您可以访问Xamarin.Forms中的本机控件吗?

是和否; - )

本机控件真正暴露且唯一安全更改的唯一位置是其Xamarin.Forms渲染器类。

但是,我们始终在基于平台的直接代码中执行此操作,我并不是说这是最佳实践,但它 当你无法控制你绑定的第三方代码时,它可以正常工作。

示例:在iOS上,您将通过以下方式转换本机对象的IntPtr:

Runtime.GetNSObject (button.NativeHandle) as UIButton;

当心:不要持有那些IntPtr派生对象的引用,将其视为瞬态!其他你将追逐幽灵崩溃

注意:如果我按照自己的方式,我会将这些第三方服务包装在自定义控件中,然后为其编写自定义渲染器 但是大部分时间工作量($)都会阻止。

那你怎么做呢:

在基于Xamarin.Forms的项目中,子类是一个控件,这些是非常快的子类,我们在不到一个小时的时间内完成了所有的Forms控件。

按钮子类:

public class NButton : Button
{
    public IntPtr NativeHandle;

    public NButton ()
    {
    }
}

在每个平台相关项目中,子类化本机渲染:

按钮渲染子类:

的iOS:

public class NButtonRenderer : ButtonRenderer
{
    public NButtonRenderer ()
    {
    }

    protected override void OnElementChanged (ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged (e);

        if (Control != null) {
            (e.NewElement as NButton).NativeHandle = Control.Handle;
        }

        if (e.OldElement != null) {
            (e.NewElement as NButton).NativeHandle = IntPtr.Zero;
        }
    }

}

的Android:

public class NButtonRenderer : ButtonRenderer
{
    public NButtonRenderer ()
    {
    }

    protected override void OnElementChanged (ElementChangedEventArgs<NButton> e)
    {
        base.OnElementChanged (e);

        if (Control != null) {
            (e.NewElement as NButton).NativeHandle = Control.Handle;
        }

        if (e.OldElement != null) {
            (e.NewElement as NButton).NativeHandle = IntPtr.Zero;
        }
    }
}

注意:请务必注册:

[assembly:ExportRenderer(typeof(NButton),typeof(NButtonRenderer))]

为您的每个平台创建一个依赖关系服务

参考:https://developer.xamarin.com/guides/xamarin-forms/dependency-service/

示例:IDateTimeDialog接口

public interface IDateTimeDialog
{
    Task<DateTime> ShowDateTimeDialog (DateTime dateTime, NButton button);
}

现在您可以访问本机控件:

在特定平台中,实现您定义的接口方法:

    async public Task<DateTime> ShowDateTimeDialog (DateTime dateTime, NButton button)
    {

        // Do not hold a reference the following object, treat it as transient!
        UIButton foo = Runtime.GetNSObject (button.NativeHandle) as UIButton;
        ~~~~~
        return dateTime;
    }