Передача двух параметров команды с помощью привязки WPF

у меня есть команда, которую я выполняю из своего файла XAML, используя следующий стандартный синтаксис:

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

это работало нормально, пока я не понял, что мне нужны две части информации из представления, чтобы сделать эту операцию полной так, как ожидают пользователи (ширина и высота холста specfically).

Кажется, что можно передать массив в качестве аргумента моей команде, но я не вижу способа указать привязку к моим двум холстам свойства в CommandParameter:

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

Как передать ширину и высоту моей команде? Не похоже, что это возможно с помощью команд из XAML, и мне нужно подключить обработчик щелчка в моем codebehind, чтобы получить эту информацию для передачи моему методу масштабирования.

4 ответов


во-первых, если вы делаете MVVM, у вас обычно есть эта информация, доступная вашей виртуальной машине через отдельные свойства, связанные с представлением. Это избавляет вас от необходимости передавать какие-либо параметры в ваши команды.

однако вы также можете использовать multi-bind и конвертер для создания параметров:

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

в преобразователе выбранного решения необходимо добавить значения.Clone () в противном случае параметры в команде end null

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

    ...
}

используйте Кортеж в конвертере, а в 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;
}

об использовании кортежа в конвертере, было бы лучше использовать '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;
    }      
} 

тогда логика выполнения в команде может быть такой

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

и multi-bind с конвертером для создания параметров (с двумя объектами 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>