2010-02-18 17 views
9

Ho un UserControl che aggiunge un CommandBinding alla sua raccolta CommandBindings per gestire un comando specifico. Successivamente, utilizzo questo controllo in una finestra e desidero aggiungere un altro binding a quello stesso controllo per aggiungere ulteriore comportamento. Il problema però è che quando faccio questo sembra che quando aggiungo un altro CommandBind alla raccolta CommandBindings di un controllo esso sostituisca qualsiasi legame già creato per lo stesso comando. Quindi, sembra che un controllo possa avere un solo CommandBinding per controllo, è corretto?Posso avere più CommandBindings per lo stesso comando sullo stesso controllo?

Vedere il seguente esempio di codice che tenta di impostare due CommandBindings per lo stesso comando di salvataggio.

<Window x:Class="MultipleCommandBindings.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Window.CommandBindings> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed" /> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed" /> 
</Window.CommandBindings> 
<Grid> 
    <Button Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,25,88" 
      Name="button1" 
      VerticalAlignment="Bottom" 
      Width="75" 
      Command="Save">Button</Button> 
</Grid> 

Originariamente mi aspettavo sia un tempo di compilazione o di un'eccezione di runtime quando ha scritto questo codice, ma sono rimasto sorpreso che non si lamentava. Poi sono rimasto deluso dal fatto che il mio gestore CommandBinding_Executed viene chiamato una volta invece del doppio come speravo.

Aggiornamento: Dopo un po 'di prove sembra che il mio secondo CommandBinding non sovrascrive il mio primo, ma invece sembra che anche se non sto impostazione gestito per vero nel mio gestore di eventi che il legame il primo comando inghiotte il comando. Sono abbastanza sicuro a questo punto che la soluzione al mio problema è capire perché il comando indirizzato non si sta propagando oltre il primo gestore anche se Handled non è impostato su true.

Aggiornamento: ho trovato this great little tidbit di informazioni che conferma solo alcuni dei comportamenti strani dietro comando di routing in WPF.

Aggiornamento: Un pensiero su come aggirare il fatto che sembra che non ci può essere un solo CommandBinding efficace per il comando è che sembra che la classe predefinita CommandBinding espone eseguito e CanExecute come eventi che naturalmente come tutti gli eventi possono avere più gestori. L'idea è quindi di avere un modo diverso dal metodo CommandBindings.Add standard per aggiungere altri gestori a un comando. Forse questo potrebbe essere fatto tramite un metodo di estensione sulla classe Control e la combinazione con una classe personalizzata CompositeCommandBinding che ci consente di aggregare più associazioni all'interno di un binding principale.

+0

L'unica soluzione a cui posso pensare è iscriversi all'evento Click di Button, quindi lanciare ViewCode di View come ViewModel e utilizzare manualmente var per eseguire i comandi 2. –

risposta

1

Non conosco la risposta alla tua domanda, ma l'uso di Reflector mi sembra ragionevole.

Mi chiedo perché lo stai facendo? Forse ha più senso usare lo schema Composite per aggregare i comportamenti, piuttosto che provare a combinare i collegamenti dei comandi?

+1

+1 per la nozione che si dovrebbe avere solo 1 legame nella vista e lasciare che più comportamenti vengano richiamati più in basso nello stack. –

+0

Bene, nel mio caso ho un controllo utente che può essere la fonte di diversi tipi di comandi che vengono propagati e che provengono da un controllo interno. All'interno del controllo utente, desidero essere consapevole di quando uno di questi comandi viene emesso in modo da consentire al ViewModel di avviare alcuni altri processi di cui il risultato finale sarà esposto tramite il mio UserControl (View). Posso legare alla proprietà che sto esponendo e vedere quando è cambiato in oder per sapere quando è pronto per l'uso, ma guardo le informazioni sul tipo di comando effettivo che ha avviato l'intero processo. – jpierson

3

Finora sono stato in grado di trovare una soluzione alternativa per questo problema che consiste nel gestire il comando a due diversi livelli nella struttura logica. Nell'esempio seguente gestisco il comando Salva nella mia griglia e poi di nuovo all'interno dell'elemento Finestra.

<Window x:Class="MultipleCommandBindings.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<Window.CommandBindings> 
    <CommandBinding Command="Save" 
        Executed="CommandBinding_Executed2"/> 
</Window.CommandBindings> 
<Grid> 
    <Grid.CommandBindings> 
     <CommandBinding Command="Save" 
         Executed="CommandBinding_Executed1" /> 
    </Grid.CommandBindings> 

    <Button Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,25,88" 
      Name="button1" 
      VerticalAlignment="Bottom" 
      Width="75" 
      Command="Save">Button</Button> 
</Grid> 

Per arrivare a questo lavoro il mio codice dietro ha bisogno anche di propagare manualmente l'esecuzione di comando per il livello successivo.

private void CommandBinding_Executed1(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Executed 1!"); 
     var command = e.Command as RoutedUICommand; 
     command.Execute(e.Parameter, this); 
    } 

    private void CommandBinding_Executed2(object sender, ExecutedRoutedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Executed 2!"); 
    } 

Se qualcuno ha un'idea migliore su come posso monitorare un comando ancora lasciare che si propagano naturalmente l'albero mi piacerebbe vederlo altrimenti potrebbe solo ricorrere a questa soluzione.

Problemi correlati