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의 명령을 사용하여 이것이 가능하지 않은 것으로 보이며이 정보를 내 확대 방법으로 전달하려면 코드 숨김에 클릭 처리기를 연결해야합니다.


[ 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

@Jason : 어느 쪽이든 할 수 있습니다. 즉, 뷰 푸시가 뷰 모델로 다시 변경되거나 뷰 모델이 뷰로 푸시 변경됩니다. 양방향 바인딩을 사용하면 두 옵션 중 하나를 사용할 수 있습니다.
Kent Boogaart

내 프로그램에서 OnExecute 메서드 매개 변수는 null 값을 가진 배열이지만 변환기에서 값은 예상대로입니다
Alex David

2
OnExecute 메서드에서 매개 변수가 null이고 버튼을 클릭 한 후에 YourConverter.Convert ()가 호출되지 않았습니다. 왜?
SubmarineX

3
작동하지 않습니다. 버튼을 누를 때 매개 변수가 null입니다.
adminSoftDK

38

선택한 솔루션의 변환기에서 값을 추가해야합니다. 그렇지 않으면 명령의 매개 변수가 널을 종료합니다.

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

    ...
}

6
안녕하세요, Clone ()을 추가하면 작동합니다. :) 차이점을 설명해 주시겠습니까? 왜 Clone ()이 작동 해야하는지 이해가되지 않습니다. 감사합니다.
adminSoftDK

내가 틀렸을 수도 있지만 이것이 (1267 행) 나에게 이유가 될 것 같습니다. referencesource.microsoft.com/#PresentationFramework/src/…
maxp

14

변환기에서 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>

" 값이 정적 인 경우 ": 정적 자원이란 무엇입니까? 예를 들어 질문에 Canvas Width 및 Height가 언급되어 있습니다. 이 값은 일정하지 않지만 정적입니까? 이 경우 XAML은 무엇입니까?

2
"정적"대신 "일정"으로 작성해야합니다. 정적 리소스는 실행 중에 변경되지 않는 리소스입니다. 당신이 사용하는 경우 SystemColors예를 들어, 당신은 사용해야하는 DynamicResource대신 StaticResource사용자가 실행 중 제어판을 통해 시스템 색상을 변경할 수 있기 때문이다. 캔버스 Width이며 Height리소스가 아니며 정적이 아닙니다. 에서 상속 된 인스턴스 속성이 있습니다 FrameworkElement.
Maxence

2

변환기에서 Tuple을 사용하는 경우 'string'개체를 제한하지 않고 모든 유형의 개체에 대해 작동하도록 'string'대신 'object'를 사용하는 것이 좋습니다.

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 및 명령 실행 기능을 보여주었습니다)
Caleb W.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.