Передайте метод в качестве параметра объекту XAML

#c# #xaml #xamarin #xamarin.forms

#c# #xaml #xamarin #xamarin.forms

Вопрос:

В настоящее время я работаю с a CustomObject , который нуждается в a CustomObjectRenderer для каждой платформы.

Я хотел бы передать метод в качестве параметра этому объекту со стороны XAML, чтобы я мог использовать этот обратный вызов из моего средства визуализации.

 <control:CustomObject Callback="CallbackFunction"/>
 

Затем CallbackFunction(object param) он объявляется в MainPage.xaml.cs части PCL.

 public partial class MainPage : ContentPage
{
    public MainPage()
    {
        base.BindingContext = this;
    }

    public void CallbackFunction(object param)
    {
        Debug.WriteLine((object as Element).Name);
    }
}
 

Так что, если я хорошо понимаю, я CustomObject должен быть таким:

 public CustomObject : Object
{
    public Action<object> Callback { get; set; }
}
 

Но у меня есть ошибка при синтаксическом анализе XAML.. Я не понимаю, почему возникает эта ошибка..

В конце, что я хочу сделать, это вызвать этот метод из средства визуализации, а затем обрабатывать вещи, выполнять действия из MainPage.xaml.cs, из части PCL.

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

Хорошо, мне немного сложно объяснить вам свою проблему, поэтому, если вы чего-то не понимаете, дайте мне знать.

Комментарии:

1. Блестящая идея. Я мог бы увидеть несколько очень полезных приложений для этого метода. Но знайте, что XAML создает экземпляры объектов и использует преобразователи строк в объекты. Для этой цели вам может понадобиться пользовательский конвертер.

2. Взгляните на мой ответ 😉

Ответ №1:

Вы можете добиться этого с помощью событий.

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

Средство визуализации

 public class MyViewRenderer : ViewRenderer<MyView, SomeNativeView>
{
    private void METHOD_CALLED_BY_EVENT(string param)
    {
        Element.RaiseEvent(param);
    }
}
 

Комментарии:

1. Спасибо, такой хороший ответ! Однако я бы предпочел обратный вызов :/ Но ваше решение мне подходит 🙂

Ответ №2:

После многих попыток, которые не сработали, у меня появилась идея, я попробовал, и она работает так, как я хотел, задав свой вопрос.


Сначала создайте свой пользовательский объект!

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

Поэтому мы используем Action which является контейнером для метода / обратного вызова. Но в моем примере мы будем использовать Action<object> . Почему? Поскольку это позволит нам иметь объект, имеющий параметр для нашего обратного вызова, поэтому мы сможем вернуть данные из средства визуализации.

Затем создайте страницу с именем MainPage.xaml, например. В части XAML этой новой страницы добавьте следующий код:

 <?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>
 

В этом XAML нас интересуют две части.

  • Ссылки на XAML ‘References’

    xmlns:control="clr-namespace:Project.CustomControl;assembly=Project"

С помощью этого xmlns вы можете получить доступ к своему пользовательскому элементу управления.

  • Содержимое страницы

    <ContentPage.Content>
    <control:CustomView MainPageCallback="{Binding MainPageCallbackAction}"
    VerticalOptions="Fill" HorizontalOptions="Fill"/>
    </ContentPage.Content>

Теперь мы привязываем MainPageCallback наш объект к объекту MainPageCallbackAction , объявленному на стороне C #.

После этого наш MainPage.xaml.cs будет выглядеть так:

 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");
        });
    }
}
 

Теперь последнее, на что нужно обратить внимание, — это 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);
    }
}
 

А затем, взгляните на результат, вы сможете увидеть следующее:

  • Добро пожаловать на обратный вызов 🙂
  • Emixam23 — Пример

Я надеюсь, что этот ответ понятен и поможет вам!