使用WPF绑定传递两个命令参数


155

我有一个使用以下标准语法从XAML文件执行的命令:

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

在我意识到我需要从视图中获取两条信息以使此操作完成用户期望的方式(具体来说是画布的宽度和高度)之前,此方法一直有效。

似乎可以将数组作为参数传递给命令,但是我看不到有一种方法可以在CommandParameter中指定对两个画布属性的绑定:

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

如何将宽度和高度都传递给命令?使用XAML中的命令似乎不可能实现这一点,并且我需要在我的代码背后连接一个单击处理程序,以使此信息传递给我的zoom方法。


[ stackoverflow.com/questions/58114752/…上述解决方案。我遇到了同样的问题。)
user1482689 '19

Answers:


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

@杰森:你可以做任何一种。也就是说,将视图推送更改回视图模型,或者将视图模型推送更改为视图。双向绑定将使您可以选择使用其中任何一个。
肯特·布加亚特

在我的程序中,OnExecute方法参数是一个具有空值的数组,但是在转换器中,这些值是预期的
Alex David

2
我发现OnExecute方法中该参数为null,单击该按钮后也未调用YourConverter.Convert()。为什么?
SubmarineX

3
这不起作用,当按下按钮时,参数为空
adminSoftDK 2015年

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

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

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>

如果您的值是静态的 ”:什么是静态资源?例如,问题提到“画布宽度和高度”。这些值不是恒定的,但它们是静态的吗?在这种情况下,XAML是什么?
分钟

2
我应该写“ constant”而不是“ static”。静态资源是在执行过程中不会更改的资源。SystemColors例如,如果使用,则应使用DynamicResource而不是,StaticResource因为用户可以在执行过程中通过控制面板更改系统颜色。画布WidthHeight不是资源,也不是静态的。有从继承的实例属性FrameworkElement
马克森斯

2

关于在Converter中使用Tuple,最好使用“对象”而不是“字符串”,以便它适用于所有类型的对象,而不受“字符串”对象的限制。

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

然后,Command中的执行逻辑可能像这样

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

并与转换器多绑定以创建参数(带有两个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>

我喜欢这一点,因为它可以清楚地知道转换器支持多少个参数。仅适合两个参数!(另外,您还显示了XAML和Command执行功能以全面覆盖)
Caleb W.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.