2009-08-29 19 views
122

tengo una orden que firmo de mi archivo XAML utilizando la siguiente sintaxis estándar:pasar dos parámetros de comando utilizando un WPF vinculante

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

Esto funcionó bien hasta que me di cuenta que tenía dos piezas de información de la vista para completar esta operación de la manera esperada por los usuarios (el ancho y alto del lienzo de forma específica).

Parece que es posible pasar una matriz como un argumento a mi mando, pero no veo que exista una forma de especificar la unión a mis dos propiedades del lienzo en el CommandParameter:

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

¿Cómo paso tanto ancho como alto a mi comando? No parece que esto sea posible usando comandos de XAML y necesito conectar un manejador de clics en mi código detrás para que esta información pase a mi método de zoom.

Respuesta

182

En primer lugar, si está haciendo MVVM, normalmente tendría esta información disponible para su máquina virtual a través de propiedades separadas desde la vista. Eso le ahorra tener que pasar cualquier parámetro a sus comandos.

Sin embargo, usted podría también multi-bind y utilizar un convertidor para crear los parámetros:

<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> 

en su convertidor:

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

    ... 
} 

A continuación, en el comando lógica de ejecución:

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

Gracias Kent - que era exactamente lo que estaba buscando. Me gusta su primer acercamiento mejor para que la máquina virtual conozca el "estado" de la vista a través de un enlace sin que yo tenga que pasar ningún parámetro, pero aún puedo probarlo. No estoy seguro de que me funcione aquí, ya que necesito la vista para hacer que el lienzo sea lo más grande posible y pasar este valor a la máquina virtual. Si lo enlace, ¿no tendré que establecer el ancho en la VM? En cuyo caso, la máquina virtual está vinculada a la vista? – JasonD

+0

@Jason: puedes hacerlo de cualquier manera. Es decir, haga que los cambios de inserción de vista vuelvan al modelo de vista, o haga que el modelo de vista modifique la vista. Un enlace TwoWay dará como resultado que cualquiera de las opciones esté disponible para usted. –

+0

en mi programa parámetro de método OnExecute es una matriz con valores nulos pero, en el convertidor los valores son los esperados –

13

Utilice Tuple en el convertidor y, en OnExecute, vuelva a convertir el objeto del parámetro en 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

En el convertidor de la solución elegida, se debe añadir values.Clone() de lo contrario los parámetros en el extremo de comandos nula

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

    ... 
} 
+2

Hola, esta adición con Clone() hace que funcione :) ¿Puedes explicarme qué diferencia hace? Porque no entiendo por qué necesita ese Clone() para funcionar? Gracias. – adminSoftDK

Cuestiones relacionadas