2017-07-29 4 views
0

Prisme 6.3.0Prism Xamarin Forms View est pas mis à jour après avoir modifié le modèle dans OnNavigatedTo

Je navigation à une vue et je suis les paramètres des propriétés du modèle dans la méthode OnNavigatedTo. Le problème est que la vue n'est pas mise à jour après la définition des propriétés du modèle.

Mon modèle ressemble à ceci

public class Person 
{ 
    public string Name { get; set; } 
    public string Email { get; set; } 
} 

Dans mon ViewModel

public Person Model 
{ 
    get => _model; 
    set => SetProperty(ref _model, value); 
} 

La méthode OnNavigatedTo est

public void OnNavigatedTo(NavigationParameters parameters) 
{ 
    var personModel = (Persom)parameters["Model"]; 

    _model.Email = personModel.Email; 
} 

Et en XAML

<Entry Text="{Binding Person.Email, Mode=TwoWay}"> 
</Entry> 

J'ai également essayé la méthode OnNavigatingTo mais je n'ai pas obtenu les résultats attendus. Alors que dois-je faire pour mettre à jour la vue avec les nouvelles données lorsque je navigue vers la vue?

Répondre

1

Définissez le modèle à l'aide du setter au lieu de la variable privée.

public void OnNavigatedTo(NavigationParameters parameters) 
{ 
    var personModel = (Person)parameters["Model"]; 

    Model.Email = personModel.Email; 
} 

En outre, votre XAML devrait être le changement de Person.Email à Model.Email

=========== ============ EDITED

Vous ne définissez que l'e-mail du modèle qui n'appelle pas SetProperty, de sorte que les vues ne seront pas mises à jour avec le nouvel ensemble d'e-mails. Pour que la mise à jour des vues, vous devez définir le modèle de personne à ce qui suit:

public class Person : BindableBase 
{ 
    public string Name { get; set; } 

    private string _email; 
    public string Email 
    { 
     get { return _email; } 
     set { SetProperty(ref _email, value); } 
    } 
} 

Ou au lieu de mettre simplement l'e-mail dans OnNavigatedTo, vous pouvez définir l'objet Personne.

public void OnNavigatedTo(NavigationParameters parameters) 
{ 
    var personModel = (Person)parameters["Model"]; 

    Model = personModel; 
} 
+0

Malheureusement, cela ne fonctionne pas. Vous avez raison sur le XAML, c'était une erreur quand j'ai tapé la question. J'ai essayé les deux avec '_model' et' Model' mais aucun d'entre eux n'a fonctionné. La seule façon que j'ai trouvé pour le faire fonctionner est d'appeler 'RaisePropertyChanged (" Model ");' après l'assignation, mais je ne devrais pas faire explicitement cet appel. Avez-vous une idée? – Dimitris

+0

J'ai manqué quelques informations dans votre question. J'ai mis à jour la réponse. – lowleetak

+0

La deuxième approche a fonctionné pour moi (Réglage de la propriété publique à un nouvel objet) Je n'ai pas essayé la première approche. Merci beaucoup. – Dimitris

1

Vous pouvez voir un exemple de travail complet de la façon de le faire avec le Prism Quickstart Templates.

Il y a quelques éléments clés que vous devez faire:

directement applicables aux propriétés de votre modèle est une chose merveilleuse à faire (c'est franchement quelque chose que je fais dans toutes mes applications & démos). Cependant, la liaison directe aux propriétés de votre modèle signifie que vous devez vous assurer que votre modèle est observable (implémentant INotifyPropertyChanged).

public class Person : BindableBase 
{ 
    private string _email; 
    public string Email 
    { 
     get => _email; 
     set => SetProperty(ref _email, value); 
    } 
} 

NOTE Si vous deviez utiliser PropertyChanged.Fody (comme les modèles de démarrage rapide), vous pouvez simplifier (vous n'avez pas besoin d'utiliser BindableBase, une classe de base mise en œuvre INotifyPropertyChanged, ou même simplement en ajoutant l'interface la classe travaillera):

public class Person : BindableBase 
{ 
    public string Email { get; set; } 
} 

Ensuite, vous devez avoir votre configuration ViewModel pour accepter les paramètres que vous souhaitez passer. Notez qu'avec Prism 6.3 vous avez quelques options.

À partir de Prism 6.3, INavigationAware est devenu la combinaison de deux nouvelles interfaces de navigation, INavigatingAware et INavigatedAware. Comme les noms suggèrent INavigatingAware gère la navigation qui est sur le point de se produire (avant que la vue est jamais poussée sur la pile de navigation), tandis que INavigatedAware gère la navigation qui vient de se produire. Le résultat est que si vous mettez à jour votre modèle en utilisant INavigatingAware.OnNavigatingTo lorsque l'affichage est poussé sur la pile, il affichera l'email, tandis que l'utilisation INavigatedAware.OnNavigatedTo peut entraîner une mise à jour notable de l'interface utilisateur.

Quelle que soit la méthode que vous choisissez pour vos besoins, vous pouvez aller sur la configuration de votre modèle comme suit:

public class ViewAViewModel : BindableBase, INavigatingAware 
{ 
    // This assumes you are using PropertyChanged.Fody as mentioned above 
    public Person Model { get; set; } 

    public void OnNavigatingTo(NavigationParameters parameters) 
    { 
     // Method 1: 
     Model = parameters.GetValue<Person>("Model"); 

     // Method 2: 
     if(parameters.TryGetValue<Person>("Model", out Model)) 
     { 
      // do something 
     } 

     // Method 3: 
     Model = new Person 
     { 
      Email = parameters.GetValue<string>("email"); 
     }; 
    } 
} 

NOTE Je tiens à souligner ici que d'avoir une clé de Model avec la propriété du ViewModel aussi être nommé Model n'est pas important. Il pourrait être foobar et fonctionne toujours. Ce qui est important est que le match clé comme indiqué ci-dessous:

_navigationService.NavigateAsync("ViewA", new NavigationParameters 
{ 
    { "foo", new Person { Email = "[email protected]" } } 
}); 

Model = parameters.GetValue<Person>("foo"); 

Enfin aurait besoin pour vous assurer que vous liez pas au type d'objet, mais plutôt le nom de la propriété ... Contexte Reliure de votre vue (votre ViewModel) référence le modèle Personne en utilisant le nom de propriété Model afin que votre code XAML ressemble à ceci:

<Entry Text="{Binding Model.Email}" />