代码之家  ›  专栏  ›  技术社区  ›  Morse unmounted

如何将值从自定义页面呈现器传递到Xamarin中的共享Xaml页面代码

  •  0
  • Morse unmounted  · 技术社区  · 6 年前

    我有一个Xamarin页面,为了支持特定于平台的API,我不得不使用Android本地页面呈现器。

    BasePage.xaml 将控制传递给 MyPage.xaml Navigation.PushAsync()

    <?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自定义页面呈现程序 因为上面和下面差不多。

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

    MyPage.xaml.cs BasePage.xaml.cs MyPageRenderer 结果 ButtonTapped 。我正在使用事件 ItemAdded 并在页面后面的代码中处理它。我无法访问 在android特定渲染器中仅来自共享项目的事件。

    我得更新一下 ViewModel 属于 BasePage 这样当我的页面被弹出时,我就可以通过back按钮添加新的条目来更新那里的条目内容。

    为谁工作 基本页:

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

    public event EventHandler ItemAdded;
    .
    .
    
    void SomeMethod(){
    
    ItemAdded(this, EventArgs.Empty);
    
    }
    

    问题: 如何将控制权从nativerender传递回Xamarin表单共享代码?

    MainActivity 但我想把控制权交给 基本页.xaml.cs

    2 回复  |  直到 6 年前
        1
  •  4
  •   zohre moradi    6 年前

    在“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());
            }
        }
    

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

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

    您应该这样定义事件类:

    public class SomeButtonClickedEvent : PubSubEvent<SomeButtonClickedEvent>
        {
            //you can define parameters here, if the event needs to pass a parameter.
        }
    
        2
  •  1
  •   Morse unmounted    6 年前

    关于 zohre moradi 我的答案是,我可以做到这一点如下。 IEventAggregator - Subscribe/Publish 事件方法。如果事件只在一页上需要 可以避免。

    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文件

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

    而且在

    //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
    }