web-dev-qa-db-fra.com

Passage de deux paramètres de commande à l'aide d'une liaison WPF

J'ai une commande que j'exécute à partir de mon fichier XAML en utilisant la syntaxe standard suivante:

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

Cela a bien fonctionné jusqu'à ce que je me rende compte que j'avais besoin de DEUX informations de la vue pour que cette opération se déroule comme prévu par les utilisateurs (la largeur et la hauteur de la toile, de manière spécifique).

Il semble possible de passer un tableau en tant qu'argument à ma commande, mais je ne vois pas de moyen de spécifier la liaison à mes deux propriétés de zone de travail dans CommandParameter:

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

Comment passer de la largeur et de la hauteur à ma commande? Il semble que cela ne soit pas possible avec les commandes de XAML et je dois câbler un gestionnaire de clics dans mon codebehind pour que ces informations soient transmises à ma méthode de zoom.

140
JasonD

Premièrement, si vous utilisez MVVM, ces informations sont généralement disponibles pour votre VM) via des propriétés distinctes liées à la vue. Vous évitez ainsi de devoir passer des paramètres à vos commandes.

Cependant, vous pouvez également créer une liaison multiple et utiliser un convertisseur pour créer les paramètres:

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

Dans votre convertisseur:

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

    ...
}

Ensuite, dans votre logique d'exécution de commande:

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

Dans le convertisseur de la solution choisie, vous devez ajouter values.Clone () sinon les paramètres de la commande end null

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

    ...
}
38
Daniel

Utilisez Tuple dans Converter et dans OnExecute, convertissez l'objet de paramètre 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;
}
13
Melinda

Si vos valeurs sont statiques, vous pouvez utiliser x:Array:

<Button Command="{Binding MyCommand}">10
  <Button.CommandParameter>
    <x:Array Type="system:Object">
       <system:String>Y</system:String>
       <system:Double>10</system:Double>
    </x:Array>
  </Button.CommandParameter>
</Button>
2
Maxence

En ce qui concerne l'utilisation de Tuple dans Converter, il serait préférable d'utiliser "objet" plutôt que "chaîne", afin que cela fonctionne pour tous les types d'objets sans limitation pour l'objet "chaîne".

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

Alors la logique d'exécution dans Command pourrait être comme ça

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

    // e.g. for two TextBox object
    var txtZip = (System.Windows.Controls.TextBox)param.Item1;
    var txtCity = (System.Windows.Controls.TextBox)param.Item2;
}

et liaison multiple avec convertisseur pour créer les paramètres (avec deux objets TextBox)

<Button Content="Zip/City paste" Command="{Binding PasteClick}" >
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource YourConvert}">
            <Binding ElementName="txtZip"/>
            <Binding ElementName="txtCity"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>
1
alex