2
votes

Navigation dans le shell Xamarin Forms 4 avec des paramètres complexes

Je migre une application xamarin forms 3.x avec Prism vers forms 4 avec la navigation shell.

Dois-je créer ma solution personnalisée pour transmettre des paramètres complexes à la nouvelle page ou Xamarin dispose d'une fonctionnalité intégrée pour recevoir des paramètres autres que des chaînes?

Merci.


0 commentaires

4 Réponses :


4
votes

Pour autant que je sache, et en lisant la documentation, les seuls exemples concernent la transmission de données simples, comme une chaîne lors de la navigation.

Cependant, j'ai pu trouver un problème (et une demande d'extraction), pour passer des objets / modèles, pour la prochaine version (je suppose que c'est le cas auquel vous faites référence).

Vous pouvez le suivre ici .


2 commentaires

Je suis arrivé à la même conclusion, puis j'ai créé mon propre hack pour poursuivre la migration jusqu'à ce qu'ils mettent en œuvre une solution définitive. Merci!


Ce PR mentionné dans cette réponse a été fermé. Je suppose qu'ils vont revoir cela dans MAUI (ou nous pourrions entrer un problème pour une telle amélioration MAUI)



3
votes

Vous pouvez toujours sérialiser le modèle en une chaîne JSON et le désérialiser de l'autre côté?

    public string pnlmodel
    {
        set
        {
            string derulo = Uri.UnescapeDataString(value);
            viewModel.PnL =  Task.Run(() => JsonConvert.DeserializeObject<DailyPnL>(derulo)).Result;

        }
    }

Puis dans votre code derrière:

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


1 commentaires

Cela a fonctionné pour moi, j'ai simplement dû échapper à la chaîne json avant de l'ajouter à l'URI: Uri.EscapeDataString (JsonConvert.SerializeObject (PnLClicked) ‌).



1
votes

Il existe un framework appelé Xamarin.Zero https: // github. com / markjackmilian / Xam.Zero Il vous permet d'utiliser le shell tout en vous offrant une navigation pratique entre ViewModel et ViewModel, IOC.


0 commentaires

2
votes

J'ai exécuté des tests qui semblent fonctionner. Je suis relativement nouveau dans Xamarin, je recommande donc la prudence et je souhaite la bienvenue à tout commentaire pour tout problème potentiel que je pourrais ignorer.

J'ai écrit une extension à Shell pour accepter un paramètre d'objet de données 'navigationData' comme suit: -

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

L'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);
        }
    }
}

Comme indiqué ci-dessus l'extension: -

  1. se connecte à l'événement Shell "Navigated",
  2. récupère la "vue (page) actuelle" en tant que "MyContentPage", c'est-à-dire ContentPage sous-classée,
  3. appelle une méthode InitializeAsync sur la vue en passant paramètre navigationData
  4. la vue appelle alors un InitializeAsync méthode sur le contexte de liaison (modèle de vue) en passant la navigationData sur le viewModel.

Dans la méthode d'extension ci-dessus, 'MyContentPage' est une sous-classe abstraite personnalisée de ContentPage avec une méthode InitializeAsync (navigationData) qui appelle simplement une méthode similaire sur le viewModel (contexte de liaison de la vue). De même, ViewModels sous-classe une classe ViewModelBase personnalisée qui a un InitializeAsync (navigationData) virtuel. Cela peut être remplacé dans viewModel avec l'implémentation et la gestion souhaitées des données de navigation.

Exemple simplifié de Views, ViewModels et classes de base associées illustrées ci-dessous

await Shell.Current.GoToAsync(state, navigationData, animate);


0 commentaires