Comment ouvrir une nouvelle fenêtre en utilisant MVVM Light Toolkit

j'utilise MVVM Light toolkit dans mon application WPF. Je voudrais savoir quelle est la meilleure approche pour l'ouverture d'une nouvelle fenêtre à partir d'une fenêtre existante. J'ai ce MainViewModel , qui est responsable de MainWindow de ma demande. Maintenant dans le MainView , sur un clic de bouton, je voudrais ouvrir une deuxième fenêtre sur le dessus de cela. J'ai RelayCommmand lié au Button 's Command . Dans la méthode RelayCommand , je peux créer un nouvel objet window et simplement appelez Show() , quelque chose comme ceci:

var view2 = new view2()
view2.Show()

mais je ne pense pas que le ViewModel devrait être responsable de la création du nouvel objet view2 . J'ai lu ce post WPF MVVM Get Parent from VIEW MODEL où Bugnion a suggéré de passer le message au view1 du viewmodel1 et puis view1 devrait créer le nouveau view2 . Mais je ne suis pas sûr de ce qu'il veut réellement dire en transmettant le message à la view1 ? Comment le view1 devrait-il traiter le message? Dans son code derrière ou quoi?

en ce qui Concerne, Nabeel

42
demandé sur Community 2010-08-02 13:01:38

6 réponses

passer un message de ViewModel1 à View1 signifie utiliser les capacités de messagerie dans le MVVM Light Toolkit .

par exemple, votre ViewModel1 pourrait avoir une commande appelée ShowView2Command, alors il enverrait un message pour afficher la vue.

public class ViewModel1 : ViewModelBase
{
    public RelayCommand ShowView2Command { private set; get; }

    public ViewModel1() : base()
    {
        ShowView2Command = new RelayCommand(ShowView2CommandExecute);
    }

    public void ShowView2CommandExecute()
    {
        Messenger.Default.Send(new NotificationMessage("ShowView2"));
    }
}

View1 s'enregistrerait pour recevoir des messages dans son code derrière et afficher View2 quand il reçoit le bon message.

public partial class View1 : UserControl
{
    public View1()
    {
        InitializeComponent();
        Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
    }

    private void NotificationMessageReceived(NotificationMessage msg)
    {
        if (msg.Notification == "ShowView2")
        {
            var view2 = new view2();
            view2.Show();
        }
    }
}
53
répondu Matt Casto 2010-08-02 13:33:42

Pourquoi faites-vous cette route? Son simple. Si vous remplacez votre bouton par un bouton à bascule, ou un lien hypertexte, ou tout autre nombre de commandes de type bouton, vous n'avez pas besoin de mettre à jour votre "code derrière"-c'est un principe de base du modèle MVVM. Dans votre nouveau toggleButton (ou autre), vous finissez toujours par vous lier à la même commande exacte.

par exemple, je crée un projet pour un client qui veut avoir 2 UI - un va être fondamentalement différent dans chaque façon, en termes de présentation. Tabs horizontaux vs RadPanelBar Vertical (pensez accordéon) pour la navigation. Ces deux vues peuvent pointer vers le même modèle de vue - lorsqu'un utilisateur clique sur L'onglet ordre de travail dans la vue 1, il lance la même "WorkOrderCommand" qui est lancée dans l'en-tête ordre de travail dans la barre de panneau.

dans un modèle codé, il faut coder deux événements distincts. Ici, vous n'avez qu'à code.

en outre, il permet à un concepteur utilisant mélange pour créer la mise en page qu'ils veulent. Tant qu'ils ont les crochets (Eventcommand control) en place, moi (en tant que développeur) ne pourrait pas moins se soucier de ce que le produit final ressemble.

accouplement lâche est incroyablement puissant.

4
répondu Scott Silvi 2011-01-21 22:52:17

vous pouvez faire de cette façon comme vous avez besoin de créer quelques événements et enregistrer ceux dans view et les appeler modèle de vue.et ouvrir cette fenêtre pop-up.

comme cet exemple

public class Mainclass : MainView
{
    public delegate abc RegisterPopUp(abc A);
    public RegisterPopUp POpUpEvent ;

    public RelayCommand ShowCommand { private set; get; }  


    public void ShowCommand() 
    { 
        ShowCommand("Your parameter");
    } 
}

à l'intérieur de la vue MainView mn=new MainView();

enregistrer l'événement ici comme thake mn.POpUpEvent += que de cliquer sur le bouton de l'onglet double temps

et dans les registres méthode popup à droite le code pour l'ouverture la fenêtre pop-up.

3
répondu Hoshiyar 2012-12-06 15:42:26

à moins que je ne manque le point ici - si je devais utiliser le code derrière, alors pourquoi ne pas directement mettre en œuvre l'événement button_click et ouvrir la deuxième vue?

Ce que l'Auteur semble le suggérer est vue1 -> cliquez sur le bouton -> relais de commande -> viewmodel1 -> message -> vue1 -> vue1.cs -> ouvrez la vue 2.

vous allez de toute façon sacrifier testabilité en écrivant code-derrière, alors pourquoi prendre un tel chemin?

2
répondu Pratz 2010-08-24 19:33:39

vous pouvez abstraire les traits spécifiques de la vue dans les services en utilisant l'interface générique. Dans la couche de vue, vous pouvez fournir des exemples concrets de ces services et construire des modèles de vue en utilisant la technique IOC container et Dependency Injection.

dans votre cas, vous pouvez construire une interface IWindowManager ou quelque chose de similaire qui a la méthode requise. Cela peut être implementé dans votre couche de vue. J'ai écrit un petit billet de blog récemment montrant comment résumé la modèle de comportement de dialogue hors de vue. Des répartitions similaires peuvent être utilisées pour n'importe quel service lié à l'interface utilisateur comme la Navigation, les boîtes à messages, etc.

ce lien peut être utile pour vous http://nileshgule.blogspot.com/2011/05/silverlight-use-dialogservice-to.html

beaucoup de gens utilisent également l'approche de mise à feu des événements à partir de modèles de vue qui sont souscrits sur la vue.fichier cs et à partir de là, le MessageBox ou toute autre interface liée l'action est effectuée. J'aime personnellement l'approche des services d'injection parce qu'alors vous pouvez fournir plusieurs implémentations du même service. Un exemple simple serait comment la navigation est traitée dans Silverlight et Windows Phone 7 applications. Vous pouvez utiliser le même modèle de vue mais injecter différentes implémentations du service de Navigation basé sur le type d'application.

2
répondu Nilesh Gule 2011-12-06 17:30:24

je trouve que la meilleure façon d'aborder cela, est d'ouvrir et de fermer la fenêtre à partir du modèle de vue. Comme ce lien suggère,

  1. créer une DialogCloser classe
    public static class DialogCloser
    {
        public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof(bool?), typeof(DialogCloser), new PropertyMetadata(DialogResultChanged));

        private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var window = d as Window;
            if (window != null) window.Close();
        }

        public static void SetDialogResult(Window target, bool? value)
        {
            target.SetValue(DialogResultProperty, value);
        }
    }
  1. créer un ViewModel de Base héritant de GalaSoft.MvvmLight.ViewModelBase avec des membres supplémentaires. Une fois fait, utilisez ce modèle de vue comme base pour d'autres modèles de vue.
    bool? _closeWindowFlag;
    public bool? CloseWindowFlag
    {
        get { return _closeWindowFlag; }
        set
        {
            _closeWindowFlag = value;
            RaisePropertyChanged("CloseWindowFlag");
        }
    }

    public virtual void CloseWindow(bool? result = true)
    {
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
        new Action(() =>
        {
            CloseWindowFlag = CloseWindowFlag == null ? true : !CloseWindowFlag;
        }));
    }
  1. dans la vue, liez la propriété de dépendance DialogCloser.DialogResult avec la propriété CloseWindowFlag dans le modèle de vue de base.

alors vous pouvez ouvrir/fermer/cacher la fenêtre du modèle de vue.

0
répondu Touhid Alam 2014-11-09 20:41:51