web-dev-qa-db-ja.com

WPFバインディングを使用して2つのコマンドパラメーターを渡す

次の標準構文を使用してXAMLファイルから実行しているコマンドがあります。

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

これは、ユーザーが期待する方法(キャンバスの幅と高さ)をこの操作で完了するために、ビューから2つの情報が必要であることに気付くまでうまくいきました。

配列をコマンドに引数として渡すことは可能のようですが、CommandParameterで2つのキャンバスプロパティへのバインディングを指定する方法はありません。

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

コマンドに幅と高さの両方を渡すにはどうすればよいですか? XAMLのコマンドを使用してこれが可能であるとは思えないため、この情報をズームメソッドに渡すには、コードビハインドにクリックハンドラーを接続する必要があります。

140
JasonD

まず、MVVMを実行している場合、通常、ビューからバインドされた個別のプロパティを介してVMでこの情報を利用できます。これにより、コマンドにパラメーターを渡す必要がなくなります。

ただし、マルチバインドし、コンバーターを使用してパラメーターを作成することもできます。

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

コンバーターで:

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

    ...
}

次に、コマンド実行ロジックで:

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

選択したソリューションのコンバーターで、values.Clone()を追加する必要があります。そうでない場合、コマンドのパラメーターはnullを終了します

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

    ...
}
38
Daniel

ConverterでTupleを使用し、OnExecuteでパラメーターオブジェクトを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

値が静的な場合、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

ConverterでのTupleの使用については、「string」オブジェクトの制限なしにすべてのタイプのオブジェクトで機能するように、「string」ではなく「object」を使用することをお勧めします。

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

コマンドの実行ロジックは次のようになります

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

パラメーターを作成するためのコンバーターを使用したマルチバインド(2つの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