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


155

次の標準構文を使用して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からのコマンドを使用して可能ではないようです。この情報を取得してズームメソッドに渡すには、コードビハインドでクリックハンドラーを接続する必要があります。


[ stackoverflow.com/questions/58114752/…上記のソリューション。同じ問題が発生しました。)
user1482689

回答:


240

まず、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];
}

1
ケントに感謝-それはまさに私が探していたものでした。最初のアプローチの方がいいので、パラメーターをまったく渡さなくてもVMがバインディングを通じてビューの「状態」を認識できるようにしますが、それでもテストできます。キャンバスをできるだけ大きくして、この値をVMに渡すためのビューが必要なので、ここでそれがうまくいくかどうかはわかりません。バインドした場合、VMで幅を設定する必要はありませんか?どの場合、VMはビューにバインドされますか?
JasonD、2009

@ジェイソン:どちらの方法でもできます。つまり、ビューモデルにビューの変更をプッシュするか、ビューモデルにビューの変更をプッシュします。TwoWayバインディングでは、どちらのオプションも使用できます。
ケントブーガート2009

私のプログラムではOnExecuteメソッドのパラメーターはnull値の配列ですが、コンバーターでは値は期待どおりです
Alex David

2
OnExecuteメソッドでパラメーターがnullであることがわかりました。また、ボタンをクリックした後にYourConverter.Convert()が呼び出されませんでした。どうして?
SubmarineX

3
これは機能せず、ボタンを押すとパラメーターがnullになります
adminSoftDK

38

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

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

    ...
}

6
こんにちは、Clone()を追加したことで機能します:)違いを説明してください。なぜClone()が機能する必要があるのか​​理解できないので?ありがとうございました。
adminSoftDK 2015年

私は間違っているかもしれませんが、この(ライン1267)は、それのようなルックスは、私には理由が考えられます。referencesource.microsoft.com/#PresentationFramework/src/...
をmaxP

14

タプルをコンバーターで使用し、OnExecuteでパラメーターオブジェクトをタプルにキャストします。

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

5

値が静的な場合は、次を使用できます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>

値が静的である場合」:静的リソースとは何ですか?たとえば、質問ではCanvas WidthとHeightについて言及しています。これらの値は一定ではありませんが、静的ですか?この場合、XAMLはどうなりますか?

2
「静的」ではなく「一定」と書いておくべきだった。静的リソースは、実行中に変更されないリソースです。たとえばを使用する場合、ユーザーは実行中にコントロールパネルを使用してシステムの色を変更できるため、の代わりにをSystemColors使用する必要があります。キャンバスとリソースではなく、静的ではありません。から継承されたインスタンスプロパティがあります。DynamicResourceStaticResourceWidthHeightFrameworkElement
Maxence

2

Converterでのタプルの使用については、「文字列」オブジェクトの制限なしにすべてのタイプのオブジェクトで機能するように、「文字列」ではなく「オブジェクト」を使用する方が良いでしょう。

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>

コンバーターがサポートするパラメーターの数がより明確であるため、私はこれが好きです。2つだけのパラメーターに適しています。(さらに、XAMLとコマンド実行機能をフルカバレッジで示しました)
Caleb W.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.