Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How to pass the data from the modal page to the parent page?

SerenaSerena Member ✭✭

Hello I am new to Xamarin.Forms and working on a time clock project. I am trying to achieve something like this:

Let say there is a report page and a modal page.
Report page is to show a list of time sheet during a working period in listview.
Modal page is to filter the date range of the working period.
The user clicks a button on the report page to open modal page.
On the modal page, when a user chooses to 'apply' a data range, modal page closes, and the report page shows the new list of timesheet of that data range.

Since the report page is getting certain date range of timesheet data from database, should I first pass the date range (selected from picker/date picker) to the parent page, and then make a new http request to retrieve the new data? How to pass the date data though (I am thinking using messaging center).

Or any better solution to'changing the date range and automatically update the parent list'?

Best Answer

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    How to pass the date data though (I am thinking using messaging center).

    Yes,you can use MessagingCenter to pass the date data.

    In Report page, you can subscribe to a message like this:

      MessagingCenter.Subscribe<YourModalPage, string>(this, "daterange", async (sender, arg) =>
      {
            await DisplayAlert("Message received", "arg=" + arg, "OK");
      });
    

    In YourModalPage, you can publish a message as follows after you select the date range:

      MessagingCenter.Send<this, string>(this, "daterange", "2020-09-10");
    
  • SerenaSerena Member ✭✭

    @jezh Thanks for your response. But I read a few articles saying using Messaging Center will lead to memory leak? Is it something we have to take care when using it?

    And I am attaching the screenshots to explain more about all my confusion.

    So when I clicked 'more filters' on the report page, the modal page shows up. And then when I choose a date range and click 'apply', modal page fades out. The report page shows new data.

    If the report page needs to send an HTTP request to retrieve data from database, when does it request when users apply a new date range? How to show new data faster?

    I just can't imagine the correct work flow. My assumption is: apply new date range -> pass date range to parent page -> parent page send new request to display new data.

    Can you tell me more about your thought? Thanks!

  • jezhjezh Member, Xamarin Team Xamurai

    But I read a few articles saying using Messaging Center will lead to memory leak? Is it something we have to take care when using it?

    For this question , you can check the official document : Xamarin.Forms MessagingCenter, we should pay attention to the note:

    So , we should unsubscribe from our message once we no longer wishes to receive the message.
    We can do like this:

    MessagingCenter.Unsubscribe<YourModalPage, string>(this, "daterange");
    

    For more , you can check:Unsubscribe from a message.

  • igorkr_10igorkr_10 Member ✭✭✭✭

    Use events.
    I prefer events instead of MessagingCenter because it is so easy to forget where exactly you sent a message.

  • SerenaSerena Member ✭✭

    @igorkr_10 Does 'Use events' mean EventArgs ? How to do this in viewmodel though?
    Could u show a sample or explain a lit bit more? Thank you.

  • SerenaSerena Member ✭✭

    @jezh Thanks for detailed explanation! And I am trying on another solution(but failed), would u like to take a look?

    ReportPageModel.cs:

    public class TimeReportPageModel : PageModelBase
    {
        private DateTime _startDate;
            public DateTime StartDate
            {
                get => _startDate;
                set => SetProperty(ref _startDate, value);
            }
    
            private DateTime _endDate;
            public DateTime EndDate
            {
                get => _endDate;
                set => SetProperty(ref _endDate, value);
            }
        .....
        .....
        public ICommand FilterDateRange => new Command(async () =>
            {
                await _navigationService.PushModalPageAsync<ModalPageModel>(StartDate);
            });
    
        public override async Task InitializeAsync(object navigationData)
            {
                await base.InitializeAsync(navigationData);
            }
    }
    

    The Command FilterDateRange will pass the StartDate to the modal page.

    In the ModalPageModel.cs:

    public class ModalPageModel : PageModelBase
    {
        private DateTime _selectedDate;
            public DateTime SelectedDate
            {
                get => _selectedDate;
                set => SetProperty(ref _selectedDate, value);
            }
    
        ......
        public override async Task InitializeAsync(object navigationData)
            {
                if (navigationData is DateTime startDate)
                {
                    SelectedDate = startDate;
                 }
               // return base.InitializeAsync(navigationData);
            }
    
    }
    

    So on the ModalPage.xaml there are two date picker for start date and end date. The SelectedDate is binding for one of the date picker:

     <DatePicker Date="{Binding SelectedDate, Mode=TwoWay}"
                          Format="MM/dd/yy" BackgroundColor="Transparent"
                          VerticalOptions="Start"/>
    

    This is a test and I found the navigationData is successfully passed to the modal page, which means the start date on report page is shown on the date picker in the modal page.

    The pushmodalpage method in navigationService:

    public async Task PushModalPageAsync<TPageModel>(object navigationData = null) where TPageModel : PageModelBase
            {
                var page = PageModelLocator.CreatePageFor(typeof(TPageModel));
    
               if (App.Current.MainPage is NavigationPage navPage)
                {
                    await navPage.Navigation.PushModalAsync(new NavigationPage(page));
                }
    
                if (page.BindingContext is PageModelBase pmBase)
                {
                    await pmBase.InitializeAsync(navigationData);
                }
            }
    

    Then I began to think is there a similar way to pass back the start date? Or something like, I pass the start date, and modified it in the modal page (make it equal to the date when user picks a date from date picker), and then the start date property will detect the change automatically?

  • jezhjezh Member, Xamarin Team Xamurai

    Then I began to think is there a similar way to pass back the start date?

    Yes, you can use event to achieve this function.
    Please refer to the followin code:

    1.define a interface MyInterface

    MyInterface.cs

        public delegate void MyDelegate();
    
        public interface MyInterface
        {
            event MyDelegate MyEvent;
            void PassData(string date);
        }
    

    2.implement above interface in your ReportPage

       public partial class ReportPage : ContentPage,MyInterface // implement interface `MyInterface`
        {
            public ReportPage()
            {
                InitializeComponent();
            }
    
            public event MyDelegate MyEvent;
    
            public void PassData( string date)
            {
                string mDate = date;
                Debug.WriteLine("++++++ selected date : " + mDate);
            }
      // other code
        }
    

    3.When you click 'apply' button after you choose a date range in page YourModalPage,then you can pass the selected date like this:

          ReportPage reportPage = new ReportPage();
          reportPage.MyEvent += new MyDelegate(f);
    
          reportPage.PassData("2020-09-11");
    

    4.then we can get the passed date in step2:

               public void PassData( string date)
            {
                string mDate = date;
                Debug.WriteLine("++++++ selected date : " + mDate);
            }
    
Sign In or Register to comment.