【问题标题】:Getting public variable of popped page获取弹出页面的公共变量
【发布时间】:2017-12-04 07:08:32
【问题描述】:

我正在实例化另一个页面,并为它的一个公共属性(“SomeValue”)分配一个值,如下所示:

        _btnGotoOtherPage.Clicked += async (sender, e) =>
        {
            OtherPage _otherpage = new OtherPage;
            _otherpage.SomeValue = 1033;
            await Navigation.PushAsync(_otherpage);
            return;
        };

在这个“_otherpage”内,用户可以修改这个值。

当弹出“_otherpage”时,我想看看“SomeValue”变量并对其进行处理。

MessagingSystem 不是我需要的,因为我不想在值更改时收到通知。我只想知道弹出“_otherpage”时这个值是什么。

我也不想使用 Binding(如果可能的话!),因为我觉得在处理许多此类变量时很难组织。

是否有可能通过事件来做到这一点?

我梦想的解决方案是(伪代码):

private void OnPagePopped()
{
    int iNewValue = PoppedPage.SomeValue;
}

谢谢。

【问题讨论】:

  • 没有理由不能使用 MessagingCenter。或者你昨天刚刚问了一个关于自定义事件的问题,你可以这样做。

标签: xamarin xamarin.forms


【解决方案1】:

这就是我对弹出窗口的处理方式,但它可以以相同的方式与页面样式一起使用。

这是我的小例子,期待MainPage = new NavigationPage(new Page1());

这基本上是关于在公共财产所在的页面上有一个Task。此任务可以返回公共属性的值。该任务将在 OnDisappearing 覆盖中完成并返回公共属性。

要取回值,您推送页面并等待任务 page.PagePoppedTask

using System;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace MVVMTests
{
    /// <summary>
    /// A base implementation for a page, that holds a task, 
    /// which can be completed and returns a value of type of the generic T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultContentPage<T> : ContentPage
    {
            public Task<T> PagePoppedTask { get { return tcs.Task; } }
            private TaskCompletionSource<T> tcs;

            public ResultContentPage()
            {
                tcs = new TaskCompletionSource<T>();
            }

            /// <summary>
            /// Completes the task and sets it result
            /// </summary>
            /// <param name="result"></param>
            protected /* virtual */ void SetPopupResult(T result)
            {
                if (PagePoppedTask.IsCompleted == false)
                    tcs.SetResult(result);
            }
    }

    /// <summary>
    /// Page1 exists of one button, that creates the Page2, assigns a value to a prop on the Page2
    /// and then awaits the PagePoppedTask of Page2
    /// </summary>
    public class Page1 : ContentPage
    {
        public Page1()
        {
            var button = new Button()
            {
                Text = "Go to page 2"
            };
            button.Clicked += Button_Clicked;

            Content = button;
        }

        private async void Button_Clicked(object sender, EventArgs e)
        {
            //Push the page
            var newPage = new Page2() { CoolInt = 123 };
            await App.Current.MainPage.Navigation.PushAsync(newPage);

            //Await the result
            int result = await newPage.PagePoppedTask;
            System.Diagnostics.Debug.WriteLine("Page result: " + result.ToString());
        }
    }

    /// <summary>
    /// Inherits from the ResultContentPage and sets the PagePoppedTask as soon as its Disappearing
    /// </summary>
    public class Page2 : ResultContentPage<int>
    {
        public int CoolInt { get; set; }    //Your property on the page

        public Page2()
        {
            var button = new Button()
            {
                Text = "Go back to page 1"
            };
            button.Clicked += Button_Clicked;

            Content = button;
        }

        private async void Button_Clicked(object sender, EventArgs e)
        {
            CoolInt = 321;                                      //assign dummy value to CoolInt prop and pop the page
            await App.Current.MainPage.Navigation.PopAsync();   //pop the page
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            SetPopupResult(CoolInt);    //set the result of the task (in ResultContentPage<T>)
        }
    }
}

【讨论】:

    【解决方案2】:

    如果您正在寻找一个理想的解决方案,我建议您遵循 MVVM 模式并将您的大量代码从您的页面移到视图模型中。

    我使用一个名为 FreshMvvm 的 MVVM 框架。这允许我执行视图模型以查看模型导航并在它们之间传递参数,如下所示:

    await CoreMethods.PushPageModel<BPageModel>(myParameter, true);
    

    这会将 myParameter 传递给我可以在 BPage 视图模型的 Init 方法中访问的 BPage。

    当我弹出 B 页面(通过视图模型)时,我可以将参数传回 A 页面

    await CoreMethods.PopPageModel(myReturnParam, true);
    

    我可以在 APageViewModel 的 ReverseInit 方法中访问。

    大多数 MVVM 框架都有类似的功能。

    Here are more details about FreshMvvm

    【讨论】:

      【解决方案3】:

      在页面 A 中:

      MessagingCenter.Subscribe<string>(this, "SomeMessage", (s) => HandleMessage(s));
      

      在页面 B 中:

      MessagingCenter.Send<string>("SenderOrAnythingElse", "SomeMessage");
      

      【讨论】:

      • 我不会将我的回复标记为“正确”答案,因为这种方式感觉太难看了。欢迎任何其他选择。我只是想展示一些有用的东西。
      【解决方案4】:

      PageB 中有公共变量:

      public int SomeValue { get; set; }                
      

      现在我们显示PageB:

      PageB nPageB = new PageB;
      await Navigation.PushAsync(nPageB);
      

      在 nPageB 中,用户现在可以更改 PageB 的公共变量

      //we track the "Disappearing" event of the page.
      //When it occurs, we get the value
      
      nPageB.Disappearing += async (sender1, e1) =>
      {
          Debug.WriteLine("New value is: " + nPage.SomeValue.ToString());
      };
      

      【讨论】:

      • @SushiHangover 您的建议/评论将不胜感激。
      • 这行得通,但设计很差 - 两个页面紧密耦合在一起,这通常是个坏主意
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 2014-04-19
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多