Reputation:
I have multiple platform-based dependency services that act as the interface (code not UI) to binding projects that in turn "can" produce seques to modal view controllers and for that they need which view that attached to.
After I implement the dependency interface:
public interface IProcessAndRespond
{
void gpuCalc (Byte[] data, object view);
}
In the platform code, I need to pass a Android Context/Widget/View, an iOS UIView and/or UIViewController to various platform specfic routines.
public class DateTimeDialog_iOS : IDateTimeDialog
{
public DateTimeDialog_iOS ()
{
}
void gpuCalc (Byte[] data, object view)
{
// lookup a native control by name? id?
}
}
How can I reference a native control within my gpuCalc method?
Upvotes: 2
Views: 1136
Reputation: 74209
Xamarin.Forms
?The only spot that a native control is truly exposed and mostly safe to change is within its Xamarin.Forms
renderer class.
But, we do it all the time in straight platform-dependent based code, I an not saying this is best-practice but it works and gets the job done when you can not control the 3rd-party code that you are binding to.
Runtime.GetNSObject (button.NativeHandle) as UIButton;
Note: If I had my way, I would wrap these 3rd-party services within a custom control and then write a custom renderer for it but the amount of work ($) prevents that most of the time.
So how can you do it:
In your Xamarin.Forms based project, subclass a control, these are very fast subclasses and we did all the Forms controls in less then an hour.
public class NButton : Button
{
public IntPtr NativeHandle;
public NButton ()
{
}
}
In each of your platform dependent projects, subclass a native render:
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;
}
}
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))]
public interface IDateTimeDialog
{
Task<DateTime> ShowDateTimeDialog (DateTime dateTime, NButton button);
}
Within your platform specific, implement the interface method you defined:
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;
}
Upvotes: 2