4

I'm trying to navigate between pages and bind data at same time.

This is what I have tried :

public ICommand GetIdeasCommand
{
    get
    {
        return new Command(async () =>
        {
            Ideas = await _apiServices.GetIdeasAsync();
            await Application.Current.MainPage.Navigation.PushAsync(new IdeasSinglePage(Ideas));
        });
    }
}

It is supposed the Ideas is a list of arrays I get from the json. But this approach is not helping me since I get a blank page. Also if I call this function inside the page everything is fine. This post gave me an idea : How to pass a parameter from one Page to another Page in Xamarin.Forms?

My view :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="Ideas.Pages.IdeasSinglePage"
         xmlns:vm="clr-namespace:Ideas.ViewModel;assembly=Ideas"
          Title="My Page">

<ContentPage.BindingContext>
    <vm:IdeasViewModel/>
</ContentPage.BindingContext>

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="20, 10">
                        <Label Text="{Binding Ideas}"
                               FontSize="12"
                               TextColor="RoyalBlue"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

Code behind :

public partial class IdeasSinglePage : ContentPage
{
    public IdeasSinglePage(List<Models.Ideas> ideas)
    {

      InitializeComponent();
      this.BindingContext = new IdeasSinglePage(ideas); //the app breaks here
    }
}

Thanks.

  • What is the expected output? Does 'IdeasSinglePage' has controls on it? – EvZ Dec 18 '17 at 17:21
  • I want the view to be filled with the information I get from ` Ideas = await _apiServices.GetIdeasAsync();` @EvZ –  Dec 18 '17 at 17:25
  • Please share your IdeasSinglePage code-behind and XAML if exists. @Aldo – EvZ Dec 18 '17 at 17:27
  • You can take a look at my edit @EvZ –  Dec 18 '17 at 17:33
  • Unfortunately that's not enough, where is the code behind of your IdeasSinglePage? What do you do with the passed list? – EvZ Dec 18 '17 at 17:37
  • I don't have code behind for IdeasSinglePage. I thought passing the argument and binding the data would be enough. @evz. What am I missing? –  Dec 18 '17 at 17:40
  • Your code behind needs to have a constructor that accepts the parameter that you are passing – Jason Dec 18 '17 at 17:43
  • IdeasSinglePage.cs is the code behind. – EvZ Dec 18 '17 at 17:43
  • Take a look at my edit. @EvZ –  Dec 18 '17 at 17:47
  • The problem is obvious you do nothing with the passed data. – EvZ Dec 18 '17 at 17:57

2 Answers2

7

Your problem is obvious, you are passing the data to the ContentPage but you do nothing with it. Generally speaking passing a parameter from one ViewModel to another ViewModel is a very simple problem.

Here is an illustration without XAML:

public class MyFirstPage : ContentPage
{
  public MyFirstPage()
  {
    this.BindingContext = new MyFirstPageViewModel();
  }
}

public class MyFirstPageViewModel : INotifyPorpertyChanged
{
  public ICommand<List<string>> DownloadDataCmd { get; }

  public MyFirstPageViewModel()
  {
    DownloadDataCmd = new Command<List<string>>(async () => {
        var data = await dataService.DownloadData();
        await navService.PushAsync(new MySecondPage(data));
    });
  }
}

public class MySecondPage : ContentPage
{
  public MySecondPage(List<string> downloadedData)
  {
    this.BindingContext = new MySecondPageViewModel(downloadedData);
  }
}

public class MySecondPageViewModel : INotifyPropertyChanged
{
  public List<string> Data { get; }
  public MySecondPageViewModel(List<string> downloadedData)
  {
     // Do whatever is needed with the data
     Data = downloadedData;
  }
}

Now, looking at this solution there are few questions:
1. Why not to download the data directly on the second page?
2. Why not to store the data in cache or db if you need it across the app?

EvZ
  • 11,889
  • 4
  • 38
  • 76
6

Your understanding of BindingContext is lacking. Usually you bind a ViewModel to a BindingContext. What you're doing here

this.BindingContext = new IdeasSinglePage(ideas); //the app breaks here

doesn't make sense.

You are passing as context the page you want to load ? Just delete this line completely. Since in your recent comments you said you didn't want a ViewModel to begin with, what you will do in your CodeBehind is:

public partial class IdeasSinglePage : ContentPage
{
  public IdeasSinglePage(List<Models.Ideas> ideas)
  {
    InitializeComponent();
    listViewName.ItemsSource = ideas;
  }
}

And in your xml you give your listView a Name. You need this Name for referencing the list on code behind.

Hope it helps

Greggz
  • 1,873
  • 1
  • 12
  • 31