简体   繁体   English

如何在Xamarin中将值从自定义PageRenderer传递到背后的Shared Xaml Page代码

[英]How to pass values from custom PageRenderer to Shared Xaml Page code behind in Xamarin

I have a Xamarin page in which I had to use Android native page renderer in order to support platform specific API. 我有一个Xamarin页面,在其中必须使用Android本机页面渲染器才能支持特定于平台的API。

BasePage.xaml passes control to MyPage.xaml with Navigation.PushAsync() BasePage.xaml通过Navigation.PushAsync()将控制权传递给MyPage.xaml

XAML page : MyPage.xaml XAML页面:MyPage.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"
             x:Class="Views.MyPage" Title="My Page">
    <ContentPage.Content>
    </ContentPage.Content>
</ContentPage>

Android Custom page renderer for the above is something like below. 上面的Android自定义页面渲染器如下所示。

[assembly: ExportRenderer(typeof(MyPage), typeof(MyPageRenderer))]
namespace MyApp.Droid.Renderers
{
    public class MyPageRenderer : PageRenderer
    {
        private Context _localContext;
        private global::Android.Views.View view;

        private Activity activity;
        public event EventHandler ItemAdded;

        public MyPageRenderer(Context context) : base(context)
        {
            _localContext = context;
        }

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

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                SetupUserInterface();
                SetupEventHandlers();
                AddView(view);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(@"ERROR: ", ex.Message);
            }
        }

        private void SetupUserInterface()
        {
            activity = this.Context as Activity;
            view = activity.LayoutInflater.Inflate(Resource.Layout.axml_layout, this, false);

        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);

            view.Measure(msw, msh);
            view.Layout(0, 0, r - l, b - t);
        }

        private void SetupEventHandlers()
        {
            //blah blah
        }

        private void ButtonTapped(object sender, EventArgs e)
        {

            //do something
            //Here Navigate back to page which triggered this with outcome parameter or some event 
            ItemAdded(this, EventArgs.Empty);

        }


    }
}

My intention is send back control to MyPage.xaml.cs or BasePage.xaml.cs from MyPageRenderer with outcome of ButtonTapped .I am using event ItemAdded and handle it in code behind of that page. 我的本意是控制送回MyPage.xaml.csBasePage.xaml.csMyPageRenderer与成果ButtonTapped 。我现在用的事件ItemAdded ,并在代码处理它该网页的后面。 I can not access ItemAdded event which is in android specific renderer only from shared project. 我无法仅从共享项目访问android特定渲染器中的ItemAdded事件。

I have to update ViewModel of BasePage so that I update the content of the items there when MyPage has been popped after adding new item by back button. 我必须更新BasePage ViewModel ,以便在通过“后退”按钮添加新项目后弹出MyPage时更新那里项目的内容。

Problem: I can access MyPage and BasePage but can not access renderer method and variables from Shared project because Android project depends on shared not vice versa. 问题:我可以访问MyPage和BasePage,但是不能访问Shared项目中的渲染器方法和变量,因为Android项目依赖于共享而不是相反。

I have to do something like below which is working for non-native render page BasePage: 我必须执行以下操作 ,该操作适用于非本地渲染页面 BasePage:

    var myPage = new MyPage();
    myPage.ItemAdded += OnItemAdded;
    await Navigation.PushAsync(myPage);

MyPage: 我的页面:

public event EventHandler ItemAdded;
.
.

void SomeMethod(){

ItemAdded(this, EventArgs.Empty);

}

Question: How do we pass control from NativeRenderer back to Xamarin Forms shared code? 问题:我们如何将控制权从NativeRenderer传递回Xamarin Forms共享代码?

I know we can pass control to MainActivity class but I want to pass control to BasePage.xaml.cs which I did not get from documentation. 我知道我们可以将控制权传递给MainActivity类,但是我想将控制权传递给BasePage.xaml.cs ,而这并不是我从文档中得到的。 If anyone has worked on PageRenderer please suggest. 如果有人在PageRenderer上工作过,请提出建议。

in "MyPage" Class 在“ MyPage”类中

  public class MyPage : ContentPage
    {
        public void RaiseSomeButtonClicked() => OnSomeButtonClickeded();

        private void OnSomeButtonClicked()
        {
            //by using aggregators you can publish any event and subscribe it in you BasePage.xaml.cs 
            ((App)App.Current).Container.Resolve<IEventAggregator>()
                .GetEvent<SomeButtonClickedEvent>().Publish(new SomeButtonClickedEvent());
        }
    }

in "MyPageRenderer" Class : 在“ MyPageRenderer”类中:

public class MyPageRenderer : PageRenderer
    {
        MyPage myPage;
        //...
        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            myPage = (MyPage)e.NewElement;
            //...
        }
        private void ButtonTapped(object sender, EventArgs e)
        {

            //do something
            myPage.RaiseSomeButtonClicked();

        }
    }

in "BasePage.xaml.cs", subscribe this event. 在“ BasePage.xaml.cs”中,订阅此事件。

public partial class BasePage : ContentPage
{
    private readonly SubscriptionToken _SomeButtonClickedEventSubscription;

    public BasePage()
    {
        InitializeComponent();

        _SomeButtonClickedEventSubscription = eventAggregator.Value.GetEvent<SomeButtonClickedEvent>().SubscribeAsync(async e =>
    {
        //anything you want to do when button clicked!

    }, threadOption: ThreadOption.UIThread, keepSubscriberReferenceAlive: true);
    }
}

You should define Your event class in this way: 您应该通过以下方式定义事件类:

public class SomeButtonClickedEvent : PubSubEvent<SomeButtonClickedEvent>
    {
        //you can define parameters here, if the event needs to pass a parameter.
    }

With reference to zohre moradi 's answer I could achieve this as below. 参考zohre moradi的答案,我可以如下实现。 This does not use IEventAggregator - Subscribe/Publish of events methods. 这不使用IEventAggregator事件的Subscribe/Publish方法。 If event is only required at one page IEventAggregator can be avoided. 如果仅在一页上需要事件,则可以避免使用IEventAggregator

MyPage.xaml.cs MyPage.xaml.cs

public event EventHandler ItemAdded;

public void RaiseItemAdded()
{
    ItemAdded(this, EventArgs.Empty);
}


//have to close return call back after item addition in MyPage  
public async void CallPopAsync()
{
    await Navigation.PopAsync();
}

MyPageRenderer.cs MyPageRenderer.cs

MyPage mypage;

protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
    base.OnElementChanged(e);
    mypage= (MyPage)e.NewElement;

    if (e.OldElement != null || Element == null)
    {
        return;
    }

    try
    {
        SetupUserInterface();
        SetupEventHandlers();
        AddView(view);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(@"ERROR: ", ex.Message);
    }
}       

private void ButtonTapped(object sender, EventArgs e)
{
    //do something

    myPage.RaiseItemAdded();

    //notify
    Toast.MakeText(this.Context, "Item created", ToastLength.Long).Show();

    myPage.CallPopAsync();      
}

And in BasePage.xaml.cs 并在BasePage.xaml.cs中

//in some method    
var myPage = new MyPage();
myPage.ItemAdded += OnItemAdded;
await Navigation.PushAsync(myPage);

private void OnItemAdded(object sender, EventArgs e)
{
    //call method to update binding object of viewmodel
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 APP.xaml.cs 代码中进行更改以将参数从一个页面传递到 Xamarin 中的另一个页面? - How to make change in APP.xaml.cs code to pass a parameter from one page to another in Xamarin? 如何访问后面代码中的元素,该元素在Xamarin.Foms的xaml页面中的DataTemplate中声明? - How to get access the element in code behind, which is declared inside a DataTemplate in xaml page in Xamarin.Foms? 如何将数据从自定义呈现页面发送到 Xamarin 中的共享页面 - How to send data from a Custom Rendered Page to a Shared Page in Xamarin 如何在 C# 后面的代码中读取 Xamarin Xaml x:Name? - How to read Xamarin Xaml x:Name in code behind C#? 从XAML页面绑定后的代码获取或设置INotifyPropertyChanged类的属性值 - Get or Set Property Values of INotifyPropertyChanged Class from Code Behind a Page Bound in XAML 如何将参数从xaml发送到后面的代码 - how to send argument from xaml to code behind 如何将变量从文本框传递到背后的代码回到同一页 - How to pass variable from textbox to code behind back to same page 如何从背后的代码传递JavaScript函数中的自定义字符串? - How to pass custom string in JavaScript function from code behind in? 如何通过webapi url将多个值传递给代码? - how to pass multiple values to code behind from webapi url? 来自Xaml的自定义颜色(与C#代码相同) - Custom Color from xaml equivalent in C# code-behind
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM