none
Rubban Office et MVVM RRS feed

  • Question

  • Bonjour à tous,
    voilà j'utilise le framework MVVM Light... et le Ribbon Microsoft...
    Maintenant imaginons que dans ma Fenetre, j'ai mon Ribbon et un TabControl qui contient des TabItems...
    Dans mon Ribbon j'ai un bouton "Enregistrer" (qui n'enregistre que les données du tabitem en cours) et un bouton "Enregistrer Tout" (qui enregistre toutes les données de tous tabitem).
    Pour faire ce traitement je pensais utiliser les "Messager" de MVVM Light..
    Deja pensez vous que ce soit une bonne idée ?
    Ensuite, pour le "Enregistrer Tout" j'imagine bien comment faire : j'envoie un message qui sera intersepté par tout mes ModelView de mes tabItems et qui appelle chacun SA méthode "Save"...
    Mais pour le "Enregistrer" du tabitem en cours, comment je spécifie qu'il n'est QUE pour mon "ViewModel" actuel ?
    (Même questions pour les fonctionnalité standards... (par exemple Copier, coller, Undo/Redo....)
    Merci de votre aide
    jeudi 22 septembre 2011 13:53

Réponses

Toutes les réponses

  • Bonjour,

     

    En effet, l'utilisation du Messenger me semble tout à fait appropriée dans ce cas de figure.
    Rien ne t'empêche de passer l'id du client concerné avec l'événement pour que seul celui-ci se sauvegarde. 

     

    Bon courage,


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    vendredi 23 septembre 2011 10:00
    Modérateur
  • Ok pour le messenger pour envoyer la commande au TabItemViewModel...

    cependant comment faire l'inverse, c'est à dire que en fonction du TabItemViewMOdel, j'affiche un nouvel onglet dans le ruban, ou j'active le coper/coller qui est desactiver sinon... comment mettre en place une "discussion" entre mon rubban et mon modelview (discussion dans les 2 sens)... ? 

    vendredi 23 septembre 2011 11:48
  • Pour cela tu dois utiliser les commandes et tout particulièrement les predicats "CanExecute" pour définir ce qui est actif ou non.

    Pour le reste, dans ces commandes tu peux utiliser le Messenger comme moyen de communication....


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    vendredi 23 septembre 2011 23:07
    Modérateur
  • Bonjour,

    Est-ce que vous avez testé la solution proposée ? Merci de partager avec nous les résultats,afin que d'autres personnes avec le même problème puissent profiter de cette solution.


    Cordialement, Pascal.

    Développeur Wpf/SilverLight/WinPhone7

    samedi 24 septembre 2011 06:34
    Modérateur
  • En fait je suis encore entrain de comprendre le fonctionnement global : 

    J'ai dans ma fenetre, Un COmposant Ribbon et un composant TabControl... 
    J'ai un MainModelView qui gère ma fenetre et le Ribbon. Puis un TabBarViewModel qui gère le tabControl. Ensuite, pour chaque type de "TabItem" (Affichage d'un client, affichage d'un projet...) j'ai un view model associé (TabItemClientViewModel, TabItemProjetViewModel qui dérive d'un viewModel "TabItemViewModel)

    MAintenant je ce que je ne comprends pas tres bien, c'est l'utilisation du Messenger ET du "CanExecute". Car si j'utilise "CanExecute", à quoi me sert mon Messenger car je n'ai qu'a utiliser la command directement...

    Je suis un peu perdu entre ces 2 solutions.... 

     

    lundi 26 septembre 2011 06:59
  • Le messenger te permet de communiquer entre différents éléments de ta solution technique: ici la commande du ribbon et ton viewModel enfant. Cela permet notamment un couplage faible.


    Le CanExecute est un prédicat de ta commande qui indique si la commande peut être exécutée.

    Ce que tu peux faire donc, c'est mettre à jour la valeur renvoyée par le CanExecute à réception d'un évènement via le Messenger...

     

    bon courage,


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    lundi 26 septembre 2011 07:51
    Modérateur
  • ALors j'ai essayé d'ajouter un "CanExecute" à mon ViewModel...

    dans ma fenetre MainWindow.xaml j'ai : 

            <my:Ribbon DockPanel.Dock="Top" x:Name="ribbon">
                <my:RibbonTab Header="Accueil" Name="ribtab" >
                    <my:RibbonGroup Height="83" VerticalAlignment="Top" >
                        <my:RibbonButton x:Name="btnSave" LargeImageSource="/KeepClipping;component/Images/Paste_32x32.png" Label="Enregistrer" Command="{Binding ActiveViewModel.SaveCommand}" /> 
                    </my:RibbonGroup>
                </my:RibbonTab>
            </my:Ribbon>
    
            <TabControl DockPanel.Dock="Bottom" x:Name="tabbar" ItemsSource="{Binding TabBar.Tabs}" ItemTemplate="{StaticResource TabItemHeaderTemplate}"  IsSynchronizedWithCurrentItem="True">
            </TabControl>

    dans mon MainViewModel, j'ai : 

        public class MainViewModel : ViewModelBase
        {
    
            public MainViewModel()
            {
                this.TabBar = new TabBarViewModel();
            }
    
            #region TabBar
            public TabBarViewModel TabBar { get; set; }
    
            public TabItemViewModel ActiveViewModel
            {
                get
                {
                    return  this.TabBar.SelectedTab;
                }
            }
            #endregion
    
        }

    et enfin, dans mon TabItemViewModel, je définis le CanSaveCommand : 

    public TabItemViewModel : ViewModelBase
    {
    // ...
    
            #region ICommand
            private RelayCommand _saveCommand;
            public RelayCommand SaveCommand
            {
                get
                {
                    if (this._saveCommand == null)
                    {
                        this._saveCommand = new RelayCommand(() => this.Save(null), this.CanSaveCommand);
                    }
    
                    return this._saveCommand;
                }
            }
            public bool CanSaveCommand()
            {
                return false;
            }
    
            #endregion
    
    }

    Mais ça ne fonctionne pas.. je ne comprends pas comment utiliser ce prédicat..

    lundi 26 septembre 2011 08:28
  • Re-bonjour,

     

    Une procédure : 

    1. Dans TabItemViewModel, tu stockes un booléen _canSaveCommand qui stocke la possibilité de sauvegarder dans la vue courante,
    2. Dans MainViewModel tu utilises le Messenger pour lever un évènement indiquant si la fiche courante peut ou non être sauvegardée. Par exemple à chaque changement de ActiveViewModel
    3. Dans TabItemViewModel tu t'abonnes à cet évènement et tu modifies le boolén _canSaveCommand en conséquence.

     

    PPenses à utiliser la méthode CommandManager.RequerySuggested() pour indiquer que la valeur du CanExecute a évoluée.

     

    Bon courage,

     


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    lundi 26 septembre 2011 09:03
    Modérateur
  • et j'en fait quoi de ce "CanSaveCommand" ? pourquoi devrait il être modifié ?

    Lorsque je selectionne un tabItem, le CanSaveCommand est propre à l'element selectionné...

    De plus comment rendre bon bouton "Save" desactivé par défaut ? ne devrait il pas l'être automatiquement car mon ActiveViewModel est null au démarrage de l'appli..

    lundi 26 septembre 2011 09:19
  • Tu le renvoie dans la méthode CanSaveCommand !
    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    lundi 26 septembre 2011 09:20
    Modérateur
  • mais pourquoi mon code ne fonctionne pas ?

    Est ce que je définis bien mon bouton ?

     <my:Ribbon DockPanel.Dock="Top" x:Name="ribbon">
                <my:RibbonTab Header="Accueil" Name="ribtab" >
                    <my:RibbonGroup Height="83" VerticalAlignment="Top" >
                        <my:RibbonButton x:Name="btnSave" LargeImageSource="/KeepClipping;component/Images/Paste_32x32.png" Label="Enregistrer" Command="{Binding ActiveViewModel.SaveCommand}" /> 
                    </my:RibbonGroup>
                </my:RibbonTab>
            </my:Ribbon>
    


    Le "Command="{Binding ActiveViewModel.SaveCommand}" ne devrait il pas automatiquement appeler mon CanSaveCommand ?

    EN sahant que j'ai défini ça :

    public RelayCommand SaveCommand { get; private set; }
    
    // ...
    
    this.SaveCommand = new RelayCommand(() => this.Save(null), this.CanSaveCommand);
    
    pourquoi est ce que même si je force le CanSaveCommand à retourner "False", mon bouton est toujours actif... ?

    lundi 26 septembre 2011 09:25
  • Peut être as tu une erreur de Binding dans la fenêtre d'Output ?
    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    lundi 26 septembre 2011 09:27
    Modérateur
  • exact petite erreur de binding... merci de ton aide...

     

    par contre comment rendre mon bouton "inactif" au démarrage de l'appli ? car mon "ActiveModelView" est vide...

    lundi 26 septembre 2011 09:46
  • Tu assignes false par défaut à _canSaveCommand ....
    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    lundi 26 septembre 2011 09:52
    Modérateur
  • .... le _canSaveCommand est défini via "ActiveModelView" qui est null....
    lundi 26 septembre 2011 11:07
  • Dans ce cas il faut passer par un DataTrigger comme expliqué la: 

     

    http://stackoverflow.com/questions/4423746/wpf-mvvm-disable-a-buttons-state-when-the-viewmodel-behind-the-usercontrol-is-n#4424241


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    • Marqué comme réponse CaptainChoc mardi 27 septembre 2011 08:27
    lundi 26 septembre 2011 11:59
    Modérateur
  • Ok tout fonctionne maintenant, merci de ton aide ;)
    mardi 27 septembre 2011 08:27