2010-08-30 4 views
0

J'ai une commande usercontrol avec une commande, ce que je voudrais faire est d'exécuter cette commande à partir de ViewModel de la vue contenant.Exécuter une commande usercontrol à partir d'un viewmodel

Ce serait facile à accomplir dans le code derrière, car je pourrais simplement aller "UserControl.MyCommand.Execute", mais bien sûr je veux être capable de le faire dans le ViewModel.

En théorie, ce que je voudrais faire est de lier la commande de UserControl à une commande sur le ViewModel que je peux exécuter et sera ensuite traitée par le UserControl. Quelque chose comme ceci:

... 
<local:MyControl 
     MyCommand="{Binding ViewModelsCommand}" /> 
... 

Bien sûr, cela aura l'effet inverse de ce que je veux faire, comme maintenant le ViewModelsCommand est lié à MyCommand. Alors, comment inverser cela?

Fondamentalement, je veux être en mesure de lier quelque chose comme ceci:

ViewModelsCommand = "{Binding MyControl.MyCommand}"

Toutes les idées ou l'inspiration serait la bienvenue, je ne vois pas un mode de liaison ça me permettrait de faire ça. Et je ne suis pas sûr comment accéder aux propriétés de DataContext pour la reliure (d'habitude vous feriez seulement de lier et avez deux fois manipuler ceci, mais bien sûr cela ne fonctionne pas dans ce scénario).

Merci d'avance.

+0

Comment instanciez-vous/reliez-vous vos vues et visualisez-vous des modèles? – Jay

+0

Par souci de cet exemple ... les vues sont simplement déclarées en XAML (dont la racine est une fenêtre), viewmodels sont instanciées dans le constructeur de la vue –

Répondre

1

Vous instanciez le modèle de vue dans le constructeur de la vue. Pourquoi ne pas définir explicitement la valeur lors de la construction?

public SomeView() 
{ 
     var viewModel = new SomeViewModel(); 
     viewModel.ViewModelCommand = MyCommand; // or = myControl.MyCommand 

     DataContext = viewModel; 
} 

Il est possible d'utiliser un liant avec OneWayToSource, TwoWay ou Explicit, mais vous devez toujours mettre à jour explicitement la source au moins une fois dans le code (toujours si vous utilisez Explicit).

myControl.GetBindingExpression(MyControl.MyCommandProperty).UpdateSource(); 
+0

Jay, j'aime cette approche et je vais l'implémenter pour le problème actuel. Cependant, je voudrais toujours résoudre le problème par la liaison. Cela doit être possible et je crois que ce serait une approche pratique si c'était le cas. –

+0

@Chris Je mets à jour la réponse avec plus d'informations sur l'utilisation d'une reliure. – Jay

0

Veuillez noter que la réponse suivante est incorrecte. Il semble que OneWayToSource ne se mette à jour qu'après la modification de la propriété target. Cependant, je ne supprime pas cette réponse pour informer d'autres personnes qui ne sont pas au courant de ce comportement (comme moi).

Vieille réponse (voir le texte ci-dessus)

OMI votre exemple devrait fonctionner (si MyControl.MyCommand est une propriété publique qui retourne un ICommand). Avez-vous essayé le BindingMode OneWayToSource?

<local:MyControl 
     MyCommand="{Binding ViewModelsCommand,Mode=OneWayToSource}" /> 
+0

Oui, mais quand je le fais, je reçois MyCommand est ViewModelsCommand, ce qui n'est pas ce que je veux. Je veux que ViewModelsCommand soit MyCommand. Cela a-t-il du sens?Désolé si je ne m'explique pas bien –

+0

Je suis surpris par ce comportement. Avez-vous vérifié si vous avez un ancien code de test dans le code-behind ou dans un autre emplacement qui remplace cette liaison? Peut être une liaison déclarée en code ou même une assignation statique? Si ce n'est pas le problème, créez et attachez un convertisseur de valeur qui ne fait rien que renvoyer la valeur d'entrée, puis définissez un point d'arrêt dans les deux méthodes de conversion. Après cela, vous verrez, quand l'objet est déplacé d'où à où. Je n'ai pas d'autre idée. Pour autant que je comprends, la liaison doit exactement faire ce que vous désirez, pas le contraire. – HCL

+1

@HCL La source ne sera mise à jour que si la propriété cible change, ce qu'elle ne fera jamais. Pour autant que je sache, 'OneWayToSource' ne définit pas la source lorsqu'elle est initialement liée. – Jay

0

J'utilise EventAggregator de PRISM, ou Messenger de MVVMLight pour permettre à deux ViewModels de parler, mais votre cas est légèrement différent où vous avez une vue (UserControl) parler à un ViewModel.

+0

Yup, et ce que je veux accomplir ne devrait pas avoir besoin du niveau de complexité qui serait ajouté en utilisant quelque chose comme Messenger. Je ne dis pas que Messenger est complexe, juste que je veux essentiellement passer une commande dans l'arbre visuel. –

Questions connexes