viewmodel에서 명령 사용

완료됨

viewmodel에서 UI로 데이터를 가져오는 방법과 양방향 바인딩을 사용하여 데이터를 viewmodel로 다시 가져오는 방법을 살펴보았습니다.

이렇게 양방향 바인딩을 사용하는 것은 data가 변경될 때마다 UI의 변경에 응답하는 데 권장되는 방법입니다. events로 처리하는 많은 것들을 양방향 바인딩과 MVVM으로 처리할 수 있습니다. 다른 예로는 이벤트를 사용하지 않고도 viewmodel에 부울 또는 정수 값으로 반영할 수 있는 Switch.IsToggledSlider.Value 등이 있습니다.

단, 변경 데이터에 직접 연결되지 않은 Button 또는 MenuItem 활성화와 같은 항목이 있습니다. 이러한 상호 작용에도 이벤트와 유사한 처리가 필요합니다. 이러한 UI 구성 요소는 일반적으로 데이터와 함께 일종의 논리를 호출하므로 viewmodel에 해당 논리가 있어야 합니다. 하지만 가능한 경우 이를 코드 숨김의 ClickedSelected 이벤트로 처리하지 않으려고 합니다. 가능한 한 많은 것을 viewmodel에 포함시켜 테스트할 수 있도록 하려고 합니다.

명령 패턴 사용

이러한 종류의 상호 작용이 있는 대부분의 .NET MAUI 컨트롤은 ICommand 인터페이스를 노출하는 속성에 대한 바인딩을 지원합니다. 이 속성의 이름은 Command일 가능성이 높습니다. 단추는 한 가지 예입니다.

<Button Text="Give Bonus" Command="{Binding GiveBonus}" />

컨트롤은 명령을 호출할 시기를 알고 있습니다. 예를 들어 단추를 누르면 명령이 호출됩니다. 이 예제의 명령은 viewmodel의 GiveBonus 속성에 바인딩됩니다. 속성 형식은 ICommand 인터페이스를 구현해야 합니다. 코드는 다음과 비슷합니다.

public class EmployeeViewModel : INotifyPropertyChanged
{
    public ICommand GiveBonus {get; private set;}
    ...
}

ICommand 인터페이스에는 단추를 클릭하면 호출되는 Execute 메서드가 있습니다. ICommand.Execute는 이런 식으로 Button.Click 이벤트 처리 코드를 직접 대체합니다.

전체 ICommand 인터페이스에는 컨트롤을 활성화 또는 비활성화할지 여부를 결정하는 데 사용되는 CanExecuteCanExecuteChanged의 두 가지 메서드가 더 있습니다.

예를 들어 CanExecute가 false를 반환하면 단추가 흐리게 표시될 수 있습니다.

다음은 ICommand 인터페이스가 C#로 표시되는 모양입니다.

public interface ICommand
{
    bool CanExecute(object parameter);
    void Execute(object parameter);
    event EventHandler CanExecuteChanged;
}

Command 클래스 사용

이 명령 패턴을 사용하면 UI 구현과 UI 동작을 완전히 분리한 상태로 유지할 수 있습니다. 단, 각 이벤트 처리기를 구현하기 위해 별도의 클래스를 만들어야 하는 경우에는 코드가 복잡해질 수 있습니다.

인터페이스를 구현하는 사용자 지정 클래스 여러 개를 생성하기보다는 Command 또는 Command<T>을(를) 사용하는 것이 일반적입니다. 이러한 클래스는 ICommand을(를) 구현하지만 해당 동작을 설정할 수 있는 viewmodel의 속성으로 노출합니다. 이렇게 하면 viewmodel 클래스 내에서 앞에서 설명한 GiveBonus 속성을 구현할 수 있습니다.

public class EmployeeViewModel : INotifyPropertyChanged
{
    public ICommand GiveBonus {get; private set;}
    public EmployeeViewModel(Employee model)
    {
        GiveBonus = new Command(GiveBonusExecute, GiveBonusCanExecute)
    }

    void GiveBonusExecute()
    {
        //logic for giving bonus
    }

    bool GiveBonusCanExecute()
    {
        //logic for deciding if "give bonus" button should be enabled.
    }
}

이 코드에서 Execute 동작은 GiveBonusExecute 메서드에 의해 제공됩니다. CanExecuteGiveBonusCanExecute에 의해 제공됩니다. 해당 메서드의 대리자는 Command 생성자에 전달됩니다. 이 예제에는 CanExecuteChanged에 대한 구현이 없습니다.

매개 변수가 있는 명령

ICommand 인터페이스는 CanExecuteExecute 메서드에 대해 object 매개 변수를 허용합니다. .NET MAUI는 Command 클래스를 통해 형식을 검사하지 않고 이 인터페이스를 구현합니다. 명령에 연결한 대리자는 올바른 매개 변수가 전달되었는지 확인하기 위해 자체적으로 형식 검사를 수행해야 합니다. .NET MAUI는 필요한 매개 변수의 형식을 설정하는 Command<T> 구현도 제공합니다. 단일 형식의 매개 변수를 허용하는 명령을 만들 때는 Command<T>을(를) 사용합니다.

명령 패턴을 구현하는 .NET MAUI 컨트롤은 CommandParameter 속성을 제공합니다. 이 속성을 설정하면 명령이 Execute으(로) 호출될 때 또는 CanExecute 메서드에서 상태를 확인할 때 매개 변수를 명령에 전달할 수 있습니다.

이 예에서는 문자열 값 25가 명령으로 전송됩니다.

<Button Text="Give Bonus" Command="{Binding GiveBonus}" CommandParameter="25" />

이 명령은 해당 문자열 매개 변수를 해석하고 변환해야 합니다. 강타입 매개 변수를 제공하는 방법에는 여러 가지가 있습니다.

  • 특성 구문을 사용하여 CommandParameter을(를) 정의하는 대신 XAML 요소를 사용합니다.

    <Button Text="Give Bonus" Command="{Binding GiveBonus}">
        <Button.CommandParameter>
            <x:Int32>25</x:Int32>
        </Button.CommandParameter>
    </Button>
    
  • CommandParameter을(를) 올바른 형식의 인스턴스에 바인딩합니다.

  • CommandParameter이(가) 잘못된 형식에 바인딩된 경우 변환기를 적용하여 값을 올바른 형식으로 변환합니다.

지식 점검

1.

ICommand 인터페이스의 용도는 무엇인가요?

2.

Command 또는 Command<T> 클래스는 어떻게 ICommand 인터페이스의 사용을 간소화할 수 있나요?

3.

.NET MAUI 컨트롤에서 CommandParameter 속성의 역할은 무엇인가요?