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

Jas*_*onD 144 wpf binding command path

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

<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand}"/>
Run Code Online (Sandbox Code Playgroud)

这很好用,直到我意识到我需要从视图中获取两条信息,以便按照用户期望的方式完成此操作(画布的宽度和高度).

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

<Button Content="Zoom" 
        Command="{Binding MyViewModel.ZoomCommand" 
        CommandParameter="{Binding ElementName=MyCanvas, Path=Width}"/>
Run Code Online (Sandbox Code Playgroud)

如何将宽度和高度传递给我的命令?使用XAML中的命令似乎不太可能,我需要在代码隐藏中连接一个单击处理程序,以便将此信息传递给我的缩放方法.

Ken*_*art 226

首先,如果您正在使用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>
Run Code Online (Sandbox Code Playgroud)

在您的转换器中:

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的命令执行逻辑中:

public void OnExecute(object parameter)
{
    var values = (object[])parameter;
    var width = (double)values[0];
    var height = (double)values[1];
}
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用,当按下按钮时,参数为空 (3认同)
  • 我发现OnExecute方法中的参数为null,单击按钮后也没有调用YourConverter.Convert().为什么? (2认同)

Dan*_*iel 38

在所选解决方案的转换器中,您应该添加values.Clone(),否则命令中的参数将结束null

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨,这个Clone()的添加使它工作:)你能解释一下,它有什么不同.因为我不明白为什么它需要克隆()工作?谢谢. (6认同)

小智 13

在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;
}
Run Code Online (Sandbox Code Playgroud)


ale*_*lex 7

关于在 Converter 中使用 Tuple,最好使用“object”而不是“string”,这样它适用于所有类型的对象,而不受“string”对象的限制。

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

那么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;
}
Run Code Online (Sandbox Code Playgroud)

并与转换器多重绑定以创建参数(使用两个 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>
Run Code Online (Sandbox Code Playgroud)


Max*_*nce 7

如果您的值是静态的,您可以使用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>
Run Code Online (Sandbox Code Playgroud)

  • 我应该写“常量”而不是“静态”。静态资源是在执行过程中不会改变的资源。例如,如果您使用“SystemColors”,则应使用“DynamicResource”而不是“StaticResource”,因为用户可以在执行过程中通过控制面板更改系统颜色。画布 `Width` 和 `Height` 不是资源,也不是静态的。有从“FrameworkElement”继承的实例属性。 (2认同)