programing

WPF 바인딩을 사용한2개의 명령어파라미터 전달

lovejava 2023. 4. 9. 20:53

WPF 바인딩을 사용한2개의 명령어파라미터 전달

다음 표준 구문을 사용하여 XAML 파일에서 실행하는 명령어가 있습니다.

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

이것은, 유저가 기대하는 대로(캔버스의 폭과 높이) 작업을 완료하기 위해서, 뷰로부터 2개의 정보가 필요하다는 것을 깨닫기 전까지는 정상적으로 동작했습니다.

어레이를 인수로 명령어에 전달할 수 있을 것 같은데 명령어 파라미터에서 두 캔버스 속성에 대한 바인딩을 지정할 방법이 없습니다.

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

내 명령에 폭과 높이를 모두 전달하려면 어떻게 해야 합니까?XAML의 명령어를 사용하면 이것이 불가능할 것 같으며, 이 정보를 줌 방식으로 전달하려면 코드 뒤에 있는 클릭 핸들러를 연결해야 합니다.

첫째, 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];
}

선택한 솔루션의 변환기에서 값을 추가해야 합니다.Clone() 이외의 경우 명령어 파라미터는 null로 종료됩니다.

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

    ...
}

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

값이 정적인 경우 다음을 사용할 수 있습니다.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>

Converter에서 Tuple을 사용하는 경우에는 string이 아닌 object를 사용하는 것이 좋습니다.그러면 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;
}

및 멀티바인드와 변환기를 사용하여 파라미터를 작성합니다(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>

이 작업은 다른 접근법으로 해결할 수도 있습니다.XAML에서 변환기를 프로그래밍하고 코드를 확대하는 대신 ViewModel에서 다양한 파라미터를 집약할 수도 있습니다.그 결과 ViewModel은 모든 파라미터를 포함하는 속성을 하나 더 갖게 됩니다.

제가 현재 사용하고 있는 어플리케이션의 예이며, 토픽도 다룰 수 있습니다.범용 Relay Command가 필요합니다.https://stackoverflow.com/a/22286816/7678085

ViewModelBase는 SaveAndClose 명령에 의해 확장됩니다.범용 타입은 다양한 파라미터를 나타내는 이름 있는 태플입니다.

public ICommand SaveAndCloseCommand => saveAndCloseCommand ??= new RelayCommand<(IBaseModel Item, Window Window)>
    (execute =>
    {
        execute.Item.Save();
        execute.Window?.Close(); // if NULL it isn't closed.
    },
    canExecute =>
    {
        return canExecute.Item?.IsItemValide ?? false;
    });
private ICommand saveAndCloseCommand;

그런 다음 일반 유형에 따른 속성이 포함됩니다.

public (IBaseModel Item, Window Window) SaveAndCloseParameter 
{ 
    get => saveAndCloseParameter ; 
    set 
    {
        SetProperty(ref saveAndCloseParameter, value);
    }
}
private (IBaseModel Item, Window Window) saveAndCloseParameter;

뷰의 XAML 코드는 다음과 같습니다(클래식 클릭 이벤트에 주의해 주세요).

<Button 
    Command="{Binding SaveAndCloseCommand}" 
    CommandParameter="{Binding SaveAndCloseParameter}" 
    Click="ButtonApply_Click" 
    Content="Apply"
    Height="25" Width="100" />
<Button 
    Command="{Binding SaveAndCloseCommand}" 
    CommandParameter="{Binding SaveAndCloseParameter}" 
    Click="ButtonSave_Click" 
    Content="Save"
    Height="25" Width="100" />

뷰 뒤에 있는 코드에서 클릭 이벤트를 평가하여 파라미터 속성을 설정합니다.

private void ButtonApply_Click(object sender, RoutedEventArgs e)
{
    computerViewModel.SaveAndCloseParameter = (computerViewModel.Computer, null);
}

private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
    computerViewModel.SaveAndCloseParameter = (computerViewModel.Computer, this);
}

개인적으로 클릭 이벤트를 사용하는 것은 MVVM 패턴의 중단이 아니라고 생각합니다.프로그램 흐름 제어는 여전히 ViewModel 영역에 있습니다.

언급URL : https://stackoverflow.com/questions/1350598/passing-two-command-parameters-using-a-wpf-binding