3 votes

MVVM - Fermer une fenêtre à partir du modèle de vue

Dans mon application, j'utilise prism et j'essaie d'implémenter le concept suivant :

Il y a une fenêtre de communication qui peut avoir deux contrôles utilisateur possibles. J'ai les ViewModels pour la fenêtre et les contrôles d'utilisateur. Dans chaque contrôle utilisateur, j'ai des boutons. Pour certains boutons, j'ai besoin d'exécuter une certaine logique dans le ViewModel et lorsque la logique est terminée, fermer la fenêtre parente. J'ai essayé d'envoyer la fenêtre parant comme paramètre de commande comme ceci :

CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"

Et dans le viewModel, fermez la fenêtre en utilisant le code suivant :

// Create the command
OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
...
private void OpenChannel()
{
  // do some logic...
  CloseWindow();
}
private GalaSoft.MvvmLight.Command.RelayCommand<object> _closeCommand;
private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
{
    _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
    return _closeCommand;
}

Mais la fenêtre ne se referme toujours pas.

EDIT :

Le code XAML du contrôle de l'utilisateur est :

<Button Content="Open Channel" Command="{Binding OpenChannelCommand}" 
                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>

Le code du ViewModel du contrôle utilisateur est :

public RelayCommand OpenChannelCommand { get; set; } 
ctor() 
{
   OpenChannelCommand = new RelayCommand(OpenChannel, IsValidFields);
}     
private void OpenChannel() 
{    
   // logic 
   CloseWindow(); 
}
private GalaSoft.MvvmLight.Command.RelayCommand<object> CloseWindow()
{
    _closeCommand = new GalaSoft.MvvmLight.Command.RelayCommand<object>((o) => ((Window)o).Close(), (o) => true);
    return _closeCommand;
 }

C'est l'implémentation complète que j'ai actuellement essayé. Lorsque je place un point d'arrêt sur la méthode CloseWindow, il se produit à l'initialisation du mode de vue et après l'avoir appelé à nouveau dans la commande de clic du bouton, il ne fait rien.

2voto

Anton Tykhyy Points 12680

La fermeture de la fenêtre est la responsabilité de la vue, le modèle de vue ne doit rien savoir à ce sujet. Pas étonnant que vous vous emmêliez les pinceaux. Si vous n'avez pas besoin que la fenêtre reste à l'écran pendant que la "logique du bouton" est en cours d'exécution, il suffit d'utiliser une balise CompositeCommand de Prism (je ne l'aime pas trop car il utilise du code-behind, mais peu importe) ou équivalent pour lier deux commandes au bouton. D'un autre côté, si vous avez besoin de garder la fenêtre à l'écran pendant que la "logique du bouton" est en cours d'exécution, par exemple pour afficher la progression, et si votre modèle de vue reflète cela, alors vous pouvez ajouter une balise bool IsButtonLogicComplete à votre modèle de vue (n'oubliez pas la propriété INotifyPropertyChanged ) et lier l'état "fermé" de la fenêtre à cette propriété par le biais d'une propriété/comportement attachée comme celle-ci :

public static class AttachedProperties
{
    // in Visual Studio, the `propa` snippet inserts the boilerplate
    public static DependencyProperty ForceCloseProperty =
        DependencyProperty.RegisterAttached ("ForceClose",
        typeof (bool), typeof (AttachedProperties), new UIPropertyMetadata (false, (d, e) =>
        {
            var w  = d as Window ;
            if (w != null && (bool) e.NewValue)
            {
                w.DialogResult = true ;
                w.Close () ;
            }
        })) ;

    public static bool GetForceClose (DependencyObject obj)
    {
        return (bool) obj.GetValue (ForceCloseProperty) ;
    }

    public static void SetForceClose (DependencyObject obj, bool value)
    {
        obj.SetValue (ForceCloseProperty, value) ;
    }
}

<!-- in .xaml -->
<Window
  xmlns:local="clr-namespace:YourNamespace"
  local:AttachedProperties.ForceClose="{Binding IsButtonLogicComplete}" ...

Ainsi, les préoccupations relatives à votre vue et à votre modèle de vue seront bien séparées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X