RoutedCommands événements et PreviewExecuted Exécuté
-
10-10-2019 - |
Question
Mon problème est que je voudrais traiter une commande à plusieurs endroits. Par exemple, j'ai mon UserControl personnalisé où un bouton est lié à une commande. J'ai une commande obligatoire dans ce contrôle, mais j'ai aussi une commande de liaison dans une fenêtre qui utilise ce contrôle.
Mon but est d'effectuer une action dans le contrôle sans interrompre la manipulation de la commande dans la fenêtre.
J'ai essayé d'expérimenter avec des événements et Exécuté PreviewExecuted mais pas de chance. Ensuite, je simulé le problème dans une seule fenêtre (le code affiché ci-dessous).
<Window x:Class="CommandingEvents.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CommandingEvents="clr-namespace:CommandingEvents"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding
Command="{x:Static CommandingEvents:Window1.Connect}"
Executed="CommandBindingWindow_Executed"
PreviewExecuted="CommandBindingWindow_PreviewExecuted"/>
</Window.CommandBindings>
<Grid>
<Grid.CommandBindings>
<CommandBinding
Command="{x:Static CommandingEvents:Window1.Connect}"
Executed="CommandBindingGrid_Executed"
PreviewExecuted="CommandBindingGrid_PreviewExecuted" />
</Grid.CommandBindings>
<Button Command="{x:Static CommandingEvents:Window1.Connect}"
CommandTarget="{Binding RelativeSource={RelativeSource Self}}"
Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
namespace CommandingEvents
{
public partial class Window1
{
public static readonly RoutedUICommand Connect = new
RoutedUICommand("Connect", "Connect", typeof(Window1));
public Window1()
{
InitializeComponent();
}
private void CommandBindingWindow_Executed(object sender, ExecutedRoutedEventArgs e)
{
Console.WriteLine("CommandBindingWindow_Executed");
e.Handled = false;
}
private void CommandBindingGrid_Executed(object sender, ExecutedRoutedEventArgs e)
{
Console.WriteLine("CommandBindingGrid_Executed");
e.Handled = false;
}
private void CommandBindingWindow_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
{
Console.WriteLine("CommandBindingWindow_PreviewExecuted");
e.Handled = false;
}
private void CommandBindingGrid_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
{
Console.WriteLine("CommandBindingGrid_PreviewExecuted");
e.Handled = false;
}
}
}
Quand je frappe le seul bouton « CommandBindingWindow_PreviewExecuted » est imprimé. Pourquoi donc? J'ai essayé de mettre en e.Handled false mais il ne fait pas de différence. Quelqu'un peut-il expliquer ce comportement?
La solution
Je ne sais pas pourquoi cela se produit (et comment il est pas un bug), mais voici ce qui a été écrit dans le WPF wiki :
Il y a une particularité à propos de CommandBinding qui est extrêmement intéressant et important de savoir.
Le CommandManager utilise des événements routés d'informer les différents CommandBinding Les objets que l'exécution de la commande était invoqué (par des gestes par défaut, les liaisons d'entrée, de façon explicite, etc.).
Jusqu'à présent, cela est assez simple. Cependant, ce qui est plus important est que la volonté de CommandBinding marquer l'événement routé de la CommandManager comme manipulé dès qu'un gestionnaire est exécuté (soit PreviewExecuted ou Exécuté).
Enfin, même si votre gestionnaire a prototype qui correspond à un délégué appelé ExecutedRoutedEventHandler, la événement Exécuté du CommandBinding n'est pas un RoutedEvent mais CLR normale un événement. Réglage ou sortant de la drapeau e.Handled au changement de faux volonté rien.
Par conséquent, dès qu'un Exécuté ou gestionnaire PreviewExecuted est invoqué, le RoutedCommand arrêtera sa routage.