none
MVVM ContextMenu en fonction du ViewModel RRS feed

  • Question

  • Bonjour à tous,

    voilà j'ai un treeview avec plusieurs noeuds... chaque "type" de noeud est associé à un ViewModel (noeud "Client" : TreeViewClientViewModel ; noeud "Projet" : TreeViewProjetViewModel ...)

    Maintenant j'aimerai un contextmenu (clique droit sur un noeud) différent en fonction du type de noeud : pour un noeud "Client", j'affiche les menus "Suprimer" et "Nouveau Projet" et pour un noeud "Projet, j'affiche les menus "Déplacer" "Supprimer" et "Dupliquer"

    Quelle serai la meilleurs méthode pour réaliser cela ?

    Pour infos j'utilise MVVM Toolkit Light...

     

    Merci de votre aide

    mardi 27 septembre 2011 08:32

Réponses

  • Alors j'ai trouvé une solution, j'aimerai avoir votre avis...

    j'ai crée une nouvelle classe/structure (MenuItem) qui contient un Label et un RelayCommand...

     

     

        public class MenuItem
        {
            public string Label { get; set; }
            public RelayCommand MenuItemCommand { get; set; }
        }
    


     

    Puis dans mon TreeViewClientViewModel, j'ai une collection de MenuItem...

    Voilà comment j'initialise... :

     

    public class TreeViewClientViewModel : ViewModelBase
    {
    //...
    	public RelayCommand NewOperationCommand { get; private set; }
    	
    	public LoadContextMenu()
    	{
    		this.NewOperationCommand = new RelayCommand(this.NewOperation, this.CanNewOperationCommand);
    		
    		this.MenuItems = new ObservableCollection<MenuItem>();
    
    		MenuItem mnuNewOP = new MenuItem();
    		mnuNewOP.Label = "Nouvelle opération";
    		mnuNewOP.MenuItemCommand = this.NewOperationCommand;
    		this.MenuItems.Add(mnuNewOP);   
    	}
    }
    

    Et enfin dans mon XAML, je bind sur ma collection de MenuItem

     

    <HierarchicalDataTemplate DataType="{x:Type vm:TreeViewItemViewModel}" ItemsSource="{Binding Items}" >
                        <Border>
                            <Border.ContextMenu>
                                <ContextMenu ItemsSource="{Binding MenuItems}">
                                    <ContextMenu.Resources>
                                        <Style TargetType="MenuItem">
                                            <Setter Property="Header" Value="{Binding Label}" />
                                            <Setter Property="Command" Value="{Binding MenuItemCommand}" />
                                        </Style>
                                    </ContextMenu.Resources>
                                </ContextMenu>
                            </Border.ContextMenu>
                            <StackPanel Orientation="Horizontal">
                                <Image Width="16" Height="16" Margin="3,0" Source="{Binding Image}" />
                                <TextBlock Text="{Binding DisplayName}" />
                            </StackPanel>
                        </Border>
                    </HierarchicalDataTemplate>
    

    Qu'en pensez vous ? est ce abérent ? que ce passera t'il lors du dispose de mon TreeViewClientViewModel avec le "NewOperationCommand" ? dois je supprimer la liasions avec mon MenuItem avant ?
    Merci
    mardi 27 septembre 2011 15:08
  • Je trouve cette solution très bien. C'est d'ailleurs celle qui est utilisée dans Cinch.

     

    Bonne continuation.


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    • Marqué comme réponse CaptainChoc jeudi 29 septembre 2011 10:06
    mercredi 28 septembre 2011 08:29
    Modérateur

Toutes les réponses

  • En sachant que j'aimerai faire un truc genre "stocker la liste  "nom et commande associée" dans le viewModel.. ainsi je n'ai pas besoin de faire un "TemplateData" par type de noeud... et au chargement sur le ContextMenu, faire un espece de DataBinding sur cette liste "Nom <-> Command"

    Cependant je n'ai pas la moindre idée de comment procéder...

    Merci

    mardi 27 septembre 2011 14:37
  • Alors j'ai trouvé une solution, j'aimerai avoir votre avis...

    j'ai crée une nouvelle classe/structure (MenuItem) qui contient un Label et un RelayCommand...

     

     

        public class MenuItem
        {
            public string Label { get; set; }
            public RelayCommand MenuItemCommand { get; set; }
        }
    


     

    Puis dans mon TreeViewClientViewModel, j'ai une collection de MenuItem...

    Voilà comment j'initialise... :

     

    public class TreeViewClientViewModel : ViewModelBase
    {
    //...
    	public RelayCommand NewOperationCommand { get; private set; }
    	
    	public LoadContextMenu()
    	{
    		this.NewOperationCommand = new RelayCommand(this.NewOperation, this.CanNewOperationCommand);
    		
    		this.MenuItems = new ObservableCollection<MenuItem>();
    
    		MenuItem mnuNewOP = new MenuItem();
    		mnuNewOP.Label = "Nouvelle opération";
    		mnuNewOP.MenuItemCommand = this.NewOperationCommand;
    		this.MenuItems.Add(mnuNewOP);   
    	}
    }
    

    Et enfin dans mon XAML, je bind sur ma collection de MenuItem

     

    <HierarchicalDataTemplate DataType="{x:Type vm:TreeViewItemViewModel}" ItemsSource="{Binding Items}" >
                        <Border>
                            <Border.ContextMenu>
                                <ContextMenu ItemsSource="{Binding MenuItems}">
                                    <ContextMenu.Resources>
                                        <Style TargetType="MenuItem">
                                            <Setter Property="Header" Value="{Binding Label}" />
                                            <Setter Property="Command" Value="{Binding MenuItemCommand}" />
                                        </Style>
                                    </ContextMenu.Resources>
                                </ContextMenu>
                            </Border.ContextMenu>
                            <StackPanel Orientation="Horizontal">
                                <Image Width="16" Height="16" Margin="3,0" Source="{Binding Image}" />
                                <TextBlock Text="{Binding DisplayName}" />
                            </StackPanel>
                        </Border>
                    </HierarchicalDataTemplate>
    

    Qu'en pensez vous ? est ce abérent ? que ce passera t'il lors du dispose de mon TreeViewClientViewModel avec le "NewOperationCommand" ? dois je supprimer la liasions avec mon MenuItem avant ?
    Merci
    mardi 27 septembre 2011 15:08
  • Je trouve cette solution très bien. C'est d'ailleurs celle qui est utilisée dans Cinch.

     

    Bonne continuation.


    Jonathan ANTOINE - http://wpf-france.fr - http://www.jonathanantoine.com
    • Marqué comme réponse CaptainChoc jeudi 29 septembre 2011 10:06
    mercredi 28 septembre 2011 08:29
    Modérateur