RoutedCommands eventi eseguiti e PreviewExecuted
-
10-10-2019 - |
Domanda
Il mio problema è che mi piacerebbe gestire un comandi in più posti. Per esempio io ho la mia UserControl personalizzato in cui un pulsante è associato a qualche comando. Ho un ordine vincolante in tale controllo, ma ho anche un comando vincolante in una finestra che utilizza questo controllo.
Il mio obiettivo è quello di eseguire alcune azioni all'interno del controllo pur non interrompendo la gestione del comando nella finestra.
Ho provato a sperimentare con eventi eseguito e PreviewExecuted ma senza fortuna. Poi ho simulato il problema in una singola finestra (codice pubblicato sotto).
<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;
}
}
}
Quando mi ha colpito il pulsante unico "CommandBindingWindow_PreviewExecuted" viene stampato. Perché? Ho cercato di impostare e.Handled a false, ma non fa la differenza. Qualcuno può spiegare questo comportamento?
Soluzione
Non ho idea del perché ciò accade (e come non è un bug), ma qui è quello che è stato scritto nel WPF wiki :
C'è una particolarità su CommandBinding che è estremamente interessante e importante da sapere.
Il CommandManager utilizza eventi indirizzati a notificare alla diversa CommandBinding oggetti che esecuzione di un comando era invocata (attraverso gesti predefiniti, associazioni di input, in modo esplicito, ecc.).
Fino ad oggi, questo è abbastanza semplice. Tuttavia, ciò che è più importante è che la volontà CommandBinding celebrare l'evento indirizzato dal CommandManager come gestito, non appena un handler viene eseguito (sia PreviewExecuted o Eseguito).
Infine, anche se il gestore ha un prototipo che corrisponde a un delegato chiamato ExecutedRoutedEventHandler, il dell'evento eseguito dal CommandBinding non è un RoutedEvent ma un CLR normale evento. Impostazione o in uscita dalla Bandiera e.Handled al cambiamento volontà falsa nulla.
Quindi, non appena un Eseguito o gestore PreviewExecuted viene richiamato, il RoutedCommand fermerà la sua instradamento.