Reputation: 515
I´m migratting a xamarin forms 3.x app with Prism to forms 4 with shell navigation.
Do I have to create my custom solution to pass complex parameters to the new page or Xamarin has some buildin feature to receive other than string parameters?
Thanks.
Upvotes: 3
Views: 7989
Reputation: 498
You can user stored preferences to store complex data like:
private async void OnItemSelected(Item item)
{
if (item == null)
return;
var jsonstr = JsonConvert.SerializeObject(item);
//Clear the shared preferences in case there is any
Preferences.Clear();
//Store your complex json on a shared preference
Preferences.Set("Data", jsonstr);
await Shell.Current.GoToAsync(nameof(DetailsPage));
}
Retrieve it on the details page like:
bool hasKey = Preferences.ContainsKey("Data");
var content = Preferences.Get("Data", string.Empty);
Details details = hasKey ? JsonConvert.DeserializeObject<Model>(content) : null;
Upvotes: 0
Reputation: 164
You can always serialize the model to a JSON string and un-serializes it on the other side?
async void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
if (e.Item == null)
return;
DailyPnL PnLClicked = (DailyPnL)e.Item;
string jason = await Task.Run(() => JsonConvert.SerializeObject(PnLClicked));
await Shell.Current.GoToAsync($"viewdailypnl?pnlmodel={jason}");
//Deselect Item
((ListView)sender).SelectedItem = null;
}
Then in your code behind:
public string pnlmodel
{
set
{
string derulo = Uri.UnescapeDataString(value);
viewModel.PnL = Task.Run(() => JsonConvert.DeserializeObject<DailyPnL>(derulo)).Result;
}
}
Upvotes: 5
Reputation: 111
I've run some tests which seems to be working. I'm relatively new to Xamarin, hence recommend caution and welcome any feedback for any potential issues I may be overlooking.
I wrote an extension to Shell to accept a data object parameter 'navigationData' as follows:-
await Shell.Current.GoToAsync(state, navigationData, animate);
The extension ...
namespace Xamarin.Forms
{
public static class ShellExtensions
{
public static async Task GoToAsync(this Shell shell, ShellNavigationState state, object navigationData, bool animate=false)
{
shell.Navigated += async (sender, e) =>
{
if ((Shell.Current?.CurrentItem?.CurrentItem as IShellSectionController)?.PresentedPage is MyContentPage
p) await p.InitializeAsync(navigationData).ConfigureAwait(false);
};
await shell.GoToAsync(state, animate);
}
}
}
As shown above the extension:-
In the extension method above, 'MyContentPage' is a custom abstract subclass of ContentPage with an InitializeAsync(navigationData) method that simply calls a similar method on the viewModel (binding context of the view). Similarily, ViewModels subclass a custom ViewModelBase class that has a virtual InitializeAsync(navigationData). This can be overridden in the viewModel with the desired implementation and handling of the navigation data.
Simplified sample of Views, ViewModels and related base classes shown below
using System.Threading.Tasks;
using MyXamarinApp.ViewModels;
using Xamarin.Forms;
namespace MyXamarinApp.Views
{
public ItemDetailPage : MyContent<ItemDetailViewModel>{}
public ItemPage : MyContentPage<ItemViewModel>{}
public abstract class MyContentPage<T> : MyContentPage where T : ViewModelBase
{
protected T Vm;
protected override ViewModelBase VmBase => Vm as ViewModelBase;
protected MyContentPage()
{
BindingContext = Vm = ViewModelLocator.Resolve<T>();
}
private Comand _showDetailCommand;
public Command ShowDetailCommand
{
get { return _showDetailCommand ??= new Command(async () =>
await Shell.Current.GoToAsync("itemDetail", new NavigationDataObject())); }
}
}
public abstract class MyContentPage : ContentPage
{
protected abstract ViewModelBase VmBase { get; }
public virtual async Task InitializeAsync(object navigationData)
{
await VmBase.InitializeAsync(navigationData);
}
}
}
public class NavigationDataObject
{
'Properties' etc.
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace MyXamarinApp.ViewModels
{
public ItemViewModel : ViewModelBase{}
public ItemDetailViewModel : ViewModelBase
{
private NavigationDataObject _navData;
public override async Task InitializeAsync(object navigationData)
{
if (navigationData is NavigationDataObject navData)
{
_navData = navData;
}
await base.InitializeAsync(navigationData);
}
}
public abstract class ViewModelBase
{
public virtual Task InitializeAsync(object navigationData)
{
return Task.FromResult(false);
}
}
}
Upvotes: 6
Reputation: 830
There is a framework called Xamarin.Zero
https://github.com/markjackmilian/Xam.Zero
It lets you use shell while giving you convenient ViewModel to ViewModel navigation, IOC.
Upvotes: 1
Reputation: 7179
As far as I know, and, reading the docs, the only samples regard passing simple data, like string when navigating.
However, I was able to find an Issue (and Pull Request), for passing objects/ Models, for the next version (I assume this is the case you are referring to).
You can track it here.
Upvotes: 5