2009-08-29 10 views
122

ho un comando che sto eseguendo dal mio file XAML utilizzando la seguente sintassi standard:passando due parametri comando utilizzando un WPF vincolante

<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand}"/> 

questo ha funzionato bene fino a quando ho capito che avevo bisogno di due pezzi di informazioni da la vista per fare in modo che questa operazione completi il ​​modo in cui gli utenti si aspettano (la larghezza e l'altezza della tela in modo speculare).

Sembra che è possibile passare una matrice come un argomento al mio comando, ma non vedo che ci sia un modo per specificare l'associazione ai miei due proprietà di tela nella CommandParameter:

<Button Content="Zoom" 
     Command="{Binding MyViewModel.ZoomCommand" 
     CommandParameter={Binding ElementName=MyCanvas, Path=Width}"/> 

Come posso passare sia la larghezza che l'altezza al mio comando? Non sembra che questo sia possibile usando i comandi di XAML e ho bisogno di collegare un gestore di clic nel mio codebehind per far passare queste informazioni al mio metodo di zoom.

risposta

182

In primo luogo, se si sta eseguendo MVVM di solito queste informazioni sono disponibili per la VM tramite proprietà separate dalla vista. Questo ti evita di dover passare qualsiasi parametro ai tuoi comandi.

Tuttavia, si potrebbe anche multi-bind e utilizzare un convertitore per creare i parametri:

<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand"> 
    <Button.CommandParameter> 
     <MultiBinding Converter="{StaticResource YourConverter}"> 
      <Binding Path="Width" ElementName="MyCanvas"/> 
      <Binding Path="Height" ElementName="MyCanvas"/> 
     </MultiBinding> 
    </Button.CommandParameter> 
</Button> 

il convertitore:

public class YourConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, ...) 
    { 
     return values.Clone(); 
    } 

    ... 
} 

Poi, nella logica esecuzione del comando:

public void OnExecute(object parameter) 
{ 
    var values = (object[])parameter; 
    var width = (double)values[0]; 
    var height = (double)values[1]; 
} 
+1

Grazie Kent - che era esattamente quello che stavo cercando. Mi piace il tuo primo approccio migliore in modo che la VM conosca lo "stato" della vista attraverso un'associazione senza che debba passare alcun parametro, ma posso ancora verificarlo. Non sono sicuro che funzionerà per me qui, perché ho bisogno di vedere la tela quanto più grande possibile e passare questo valore alla VM. Se lo lego, non dovrò impostare la larghezza nella VM? In tal caso, la VM è vincolata alla vista? – JasonD

+0

@Jason: puoi farlo in entrambi i modi. Vale a dire, fare in modo che la vista spinga le modifiche al modello di vista o fare in modo che il modello di vista apporti le modifiche alla vista. Un'associazione TwoWay risulterà in entrambe le opzioni disponibili. –

+0

nel mio programma Il parametro del metodo OnExecute è un array con valori null ma, nel convertitore i valori sono come previsto –

13

Utilizzare Tupla nel convertitore e in OnExecute, riportare l'oggetto parametro su Tuple.

public class YourConverter : IMultiValueConverter 
{  
    public object Convert(object[] values, ...)  
    { 
     Tuple<string, string> tuple = new Tuple<string, string>(
      (string)values[0], (string)values[1]); 
     return (object)tuple; 
    }  
} 

// ... 

public void OnExecute(object parameter) 
{ 
    var param = (Tuple<string, string>) parameter; 
} 
35

Nel convertitore della soluzione scelta, è necessario aggiungere values.Clone() altrimenti i parametri alla fine comando vuoto

public class YourConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, ...) 
    { 
     return values.Clone(); 
    } 

    ... 
} 
+2

Ciao, questa aggiunta con Clone() lo fa funzionare :) Puoi spiegare, che differenza fa. Perché non capisco perché ha bisogno che Clone() funzioni? Grazie. – adminSoftDK

Problemi correlati