10
votes

ICommand.Canexecute étant passée null même si le commandalter est défini

J'ai un problème délicat où je lie un contextmenu à un ensemble d'objets iCommand définissant la commande et < Code> CommandParameter Propriétés sur chaque Menuitem via un style: xxx

Cependant, tandis que icommand.execute (objet) obtient Passé l'ensemble des notes sélectionnées comme il convient, icommand.canexecute (objet) (qui est appelé lorsque le menu est créé) est passé de NULL. J'ai vérifié et la collection de notes sélectionnée est correctement instanciée avant que l'appel soit effectué (en fait, il est attribué une valeur dans sa déclaration, il n'est donc jamais null ). Je ne peux pas comprendre pourquoi la canevaluage est passée null .


1 commentaires

J'ai eu le même problème. Ma solution consistait à lier la commande après le paramètre de commande en mettant simplement le réglage du paramètre de commande avant que la commande de la commande et le paramètre limité a été transmis au premier appel de canexecute .


3 Réponses :


11
votes

J'ai déterminé qu'il y ait au moins deux bugs dans le contexteMenu qui provoque des appels canexectes pour être peu fiables dans différentes circonstances. Il appelle immédiatement Canexecute lorsque la commande est définie. Les appels ultérieurs sont imprévisibles et ne sont certainement pas fiables.

J'ai passé une nuit entière une fois essayé de suivre les conditions précises dans lesquelles cela échouerait et cherchait une solution de contournement. Enfin, j'ai abandonné et éventuai de cliquer sur des gestionnaires qui a tiré les commandes souhaitées.

J'ai déterminé que l'un de mes problèmes était que la modification du DataContext du contexteMenu peut causer des éléments de canette à appeler avant la nouvelle commande ou le nouveauparameter est lié.

La meilleure solution que je connaisse à ce problème est d'utiliser vos propres propriétés ci-jointes pour la commande et la commande de commande au lieu d'utiliser les intégrées:

  • Lorsque votre propriété de commande ci-jointe est définie, abonnez-vous aux événements de clic et DataContextChanged sur le menuem, et abonnez-vous également à CommandManager.RequerySugyGed.

  • Lorsque le DataContext change, RequerySugged est entré dans ou que l'une de vos deux propriétés ci-jointes change, planifiez une opération de répartiteur à l'aide de DISPATCHER.BEGININVOKE qui appellera votre option CANexecute () et votre mise à jour isenabled sur le menuMeem.

  • Lorsque l'événement de clic se déclenche, faites la chose canexecute et s'il passe, appelez exécuter ().

    Utilisation est juste comme la commande régulière et le commandaRamètre, mais à l'aide des propriétés ci-jointes à la place: xxx

    Cette solution fonctionne et contourne tous les problèmes avec les bugs Manipulation Canexecute de contextMenu.

    Espérons que Microsoft Microsoft résoudra les problèmes de contextMenu et cette solution de contournement ne sera plus nécessaire. J'ai une affaire de reproduction assis ici quelque part que j'ai l'intention de soumettre à vous connecter. Peut-être que je devrais aller sur la balle et le faire réellement.

    Ce qui est requis, et pourquoi l'utiliser?

    Le mécanisme requis est routé de manière efficace Manipulation de l'iCommand.CanexecutéCHANGED. Dans le monde non roudécommand, chaque iCommand a sa propre liste d'abonnés à Canexecutéchanged, mais pour routécommand, tout client se souscrivant à iCommand.CanexecuTechaged va réellement abonner à CommandManager.requerySugGère. Ce modèle plus simple signifie que chaque fois qu'un canex de canex de routé peut changer, tout ce qui est nécessaire consiste à appeler CommandManager.invalidateRequerySugged (), qui fera la même chose que de tirer des icommand.canexecutéchangé, mais faites-le pour tous les routé-questionnaires simultanément et sur un fil d'arrière-plan. De plus, des invocations requises sont combinées ensemble de manière à ce que, si de nombreux changements se produisent, il suffit d'être appelé une seule fois.

    Les raisons pour lesquelles je vous ai recommandé vous abonnez à CommandManager.Requerysuggère au lieu de iCommand.CanexecuTecharged est: 1. Vous N'ayez pas besoin de code pour supprimer votre ancien abonnement et ajouter un nouveau à chaque fois que la valeur de la commande de votre commande modifie les modifications apportées et 2. CommandManager.RequerySugGed a une fonctionnalité de référence faiblement intégrée qui vous permet de définir votre gestionnaire d'événements et encore être des ordures recueillies. Faire la même chose avec ICommand vous exige de mettre en œuvre votre propre mécanisme de référence faible.

    Le côté bascule est que si vous vous abonnez à CommandManager.RequerysugyGeChaged au lieu de iCommand.CanexecuTecharged est que vous obtiendrez uniquement des mises à jour de routécommands . J'utilise des roudements exclusivement, ce n'est pas un problème pour moi, mais j'aurais dû mentionner que si vous utilisez des icommandes réguliers, vous devriez parfois envisager de faire des travaux supplémentaires de manière faiblement souscrive à iCommand.Canexecuted. Notez que si vous faites cela, vous n'avez pas besoin de vous abonner à RequerySugGèred également, depuis roudcommand.add_canexecutedChanged déjà cela pour vous.


5 commentaires

Wow c'est une solution compliquée à une chose assez simple à vouloir faire. QUESTIONS DE COUPLE: Comment utiliser CommandManager.RequerysugyGed (c'est un événement statique, que dois-je vérifier exactement?), Et quelle est la troisième propriété attachée que vous avez mentionnée, outre la commande et le commandalparameter?


Oh je vois, cette "propriété attachée à usage interne" ... ne pouvait-je pas simplement m'abonner à DataContextChanged?


J'ai eu le travail !! W00T! Merci :) toujours curieux de demander à requendsgèred tho ... Qu'est-ce que c'est exactement?


Heureux que cela fonctionnait pour vous. Je n'ai pas pensé à souscrire à DatacontextChanged. C'est mieux que d'utiliser une propriété supplémentaire attachée. Je mettrai à jour ma réponse et ajoute également une explication concernant RequySugGèred.


D'accord, j'avais toujours un peu de problème avec Canexecute toujours appelé, mais maintenant je l'ai eu d'en quelque sorte travaillé parfaitement, je pense que je pense que je vais laisser la pointe de la pointe et ne touchez rien, encore ... (Ne respirez pas !) Lol merci encore.



10
votes

Je crois que cela est lié à la question Connect connectée ici:

https://connect.microsoft.com/visualstudio/feedback/details/504976/command-canexecute-still-not-requeur-after-commandParameter -Change? wa = wsignin1.0 p>

Ma solution de contournement est la suivante: p>

  1. Créez une classe statique avec une propriété de dépendance attachée Un paramètre de commande limité li>
  2. Créez une interface personnalisée pour augmenter manuellement Canexecutéchangé sur une commande personnalisée li>
  3. Implémentez l'interface dans chaque commande qui doit connaître les changements de paramètres. P> XXX PRE> LI> ol>

    Implémentation de la commande: P>

        <Button Content="Save"
            Command="{Binding SaveCommand}"
            my:BoundCommand.Parameter="{Binding Document}" />
    


1 commentaires

Travaillé juste bien pour moi



1
votes

J'ai couru dans cette situation sur un DataGrid où j'avais besoin du menu contextuel pour reconnaître s'il faut activer ou désactiver des commandes spécifiques en fonction de la ligne sélectionnée. Ce que j'ai trouvé, c'est que oui, l'objet passé à la commande était NULL et qu'il n'a été exécuté qu'une seule fois pour toutes les lignes, qu'il y ait eu un changement ou non.

Ce que j'ai fait était d'appeler raisecanexecuteCommé sur des commandes spécifiques qui déclencheraient une activation ou une désactivation de l'événement de sélection de la grille.


xxx

l'attribution de liaison de commande xxx

résultat < p> où un inprogress est true La commande DELETE n'est pas activé

 Entrez la description de l'image ici < p> xaml xxx


0 commentaires