Reputation: 3964
I'm currently working with a CustomObject
that needs a CustomObjectRenderer
for each platform.
I would like to pass a method as parameter to this object, from the XAML side, so I would be able to use this callback, from my renderer.
<control:CustomObject Callback="CallbackFunction"/>
The CallbackFunction(object param)
is then declared in the MainPage.xaml.cs of the PCL part.
public partial class MainPage : ContentPage
{
public MainPage()
{
base.BindingContext = this;
}
public void CallbackFunction(object param)
{
Debug.WriteLine((object as Element).Name);
}
}
So, if I'm understanding well, my CustomObject
have to be like that:
public CustomObject : Object
{
public Action<object> Callback { get; set; }
}
But I have an error about XAML parsing.. I don't get why this error is thrown..
At the end, what I want to do, it's to call this method from the renderer, and then handle things, do actions from the MainPage.xaml.cs, from the PCL part.
public class CustomObjectRenderer : ObjectRenderer
{
NativeObject nativeObject;
CustomObject customObject;
protected override void OnElementChanged(ElementChangedEventArgs<CustomObject> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
customObject = e.NewElement as CustomObject;
nativeObject = Control as NativeObject;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
// Etc etc ....
private void METHOD_CALLED_BY_EVENT(object o)
{
// This method get call by the renderer event and then, I want to call
// the method CallbackFunction(object); and do actions.
customObject.Callback(o as OBJECT_PARAM);
}
}
Ok, it's a bit hard for me to explain my problem to you, so if you don't understand something, let me know.
Upvotes: 1
Views: 2033
Reputation: 3964
First, create your custom object !
CustomView
public class CustomView : View
{
public static readonly BindableProperty MainPageCallbackProperty =
BindableProperty.Create(nameof(MainPageCallback), typeof(Action<object>), typeof(CustomMap), null);
public Action<object> MainPageCallback
{
get { return (Action<object>)GetValue(MainPageCallbackProperty); }
set { SetValue(MainPageCallbackProperty, value); }
}
}
We so use Action
which is a container for a method/callback. But in my example, we will use Action<object>
. Why? Because it will allows us to have an object has paramter to our callback, so we will be able to bring data back from the renderer.
Then, create a page called MainPage.xaml by example. In the XAML part of this new page, add the following code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:Project.CustomControl;assembly=Project"
x:Class="Project.Page.MainPage">
<ContentPage.Content>
<control:CustomView MainPageCallback="{Binding MainPageCallbackAction}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
</ContentPage>
About this XAML, two parts interest us.
XAML 'References'
xmlns:control="clr-namespace:Project.CustomControl;assembly=Project"
By these this xmlns
, you can access your custom control.
Content of the page
<ContentPage.Content>
<control:CustomView MainPageCallback="{Binding MainPageCallbackAction}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
Now, we bind the MainPageCallback
of our object to the MainPageCallbackAction
, declared in the C# side.
After that, our MainPage.xaml.cs would seems like that:
public partial class MainPage : ContentPage
{
public Action<object> MainPageCallbackAction { get; set; }
public MainPage()
{
base.BindingContext = this;
MainPageCallbackAction = MainPageCallbackMethod;
InitializeComponent();
}
private void MainPageCallbackMethod(object param)
{
Device.BeginInvokeOnMainThread(() =>
{
Debug.WriteLine("Welcome to the Callback :)");
Debug.WriteLine("Emixam23 - Example");
});
}
}
Now, the last thing to look at is the CustomViewRenderer
!
public class CustomViewRenderer : ViewRenderer<CustomView, NativeView>
{
CustomView customView;
NativeView nativeView;
protected override void OnElementChanged(ElementChangedEventArgs<CustomView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
customView = e.NewElement as CustomView;
nativeView = Control as NativeView;
NativeView.CLicked += METHOD_CALLED_BY_EVENT;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
private void METHOD_CALLED_BY_EVENT(object sender, EventArgs ea)
{
customView.MainPageCallback(ea.something.information);
}
}
And then, take a look at the output, you'll be able to see the following:
I hope this answer is clear and helps you !
Upvotes: 0
Reputation: 14750
You can achieve this by using events.
MyView
public class MyView : View
{
public event EventHandler<string> MyEvent;
public void RaiseEvent(string parameter)
{
MyEvent?.Invoke(this, parameter);
}
}
Page.xaml
<local:MyView MyEvent="MyView_OnMyEvent"></local:MyView>
Page.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private void MyView_OnMyEvent(object sender, string e)
{
Debug.WriteLine(e);
}
}
Renderer
public class MyViewRenderer : ViewRenderer<MyView, SomeNativeView>
{
private void METHOD_CALLED_BY_EVENT(string param)
{
Element.RaiseEvent(param);
}
}
Upvotes: 1