CommunityToolkit.Mvvm 살펴보기 (완)

3. 특성

CommunityToolkit.Mvvm에서는 소스 생성기가 포함되어 있는데요. 이 패키지에서 제공하는 여러 특성을 추가하면 그에 걸맞는 코드를 자동으로 생성해 줍니다. 이는 속성을 구현하는 클래스의 소스 코드를 생성하는 방식으로 동작하기 때문에, 특성을 추가하기 위해서는 클래스를 partial로 선언해야 합니다.

이 단락에서는 CommunityToolkit.Mvvm 패키지에서 제공하는 여러 특성을 소개하고 그 기능을 간략하게 알아보도록 하겠습니다.

1) ObservableProperty

ObservableProperty 특성은 ObservableObject를 상속하는 클래스 또는 INotifyPropertyChanged 등의 특성을 추가한 클래스에서 사용할 수 있습니다. 이 특성은 필드에 추가할 수 있으며, 특성 추가 시 앞서 설명한 INotifyPropertyChanged 인터페이스 기반의 값 변경 알림을 비롯해 INotifyPropertyChanging의 값 변경 중 알림 등을 구현하는 속성을 자동으로 생성합니다.

이 때 자동 생성되는 속성의 이름은 ObservableProperty 특성이 추가된 필드 변수명을 PascalCase(UpperCamelCase)로 치환한 이름이 됩니다. 따라서 ObservableProperty 특성을 추가할 필드의 변수명은 대문자로 시작할 수 없으며, lowerCamelCase여야 합니다. 다만 _나 m_의 접두사는 인식됩니다.

  • text, _text, m_text = 정상 인식(생성되는 속성명: Text)
  • Text = 컴파일 에러 발생

또한 이 특성을 추가하는 경우 값이 변경되는 중이나 값이 변경된 후 호출되는 부분 메서드를 사용할 수 있습니다. 이해를 돕기 위해 소스 생성기에 의해 생성되는 부분 클래스의 코드를 첨부해 보겠습니다.

public partial class LoginViewModel : ObservableObject
{
    [ObservableProperty]
    private string? _id;
}

// 소스 생성기로 자동 생성된 부분 클래스
partial class LoginViewModel
{
    public string? Id
    {
        get => _id;
        set
        {
            if (!global::System.Collections.Generic.EqualityComparer<string?>.Default.Equals(_id, value))
            {
                OnIdChanging(value);
                OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Id);
                _id = value;
                OnIdChanged(value);
                OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Id);
            }
        }
    }
    partial void OnIdChanging(string? value);
    partial void OnIdChanged(string? value);
}

Id 속성의 setter를 확인해 보면 앞서 설명한 값 변경에 관련된 이벤트를 발생할 메서드인 OnPropertyChanging, OnPropertyChanged 메서드 외에 OnIdChainging, OnIdChanged 메서드가 호출되는 것을 볼 수 있으며, 그 밑에는 해당 메서드가 부분 메서드의 형태로 선언되어 있는 것을 확인할 수 있습니다.

따라서 개발자는 해당 부분 메서드를 구현함으로써 해당 속성 값이 변경되는 중이나 변경된 후 추가적인 동작을 하도록 만들 수 있습니다.

public partial class LoginViewModel : ObservableObject
{
    [ObservableProperty]
    private string? _id;

	public bool CanLogin => string.IsNullOrWhiteSpace(Id);

	partial void OnIdChanged(string? value)
	{
		OnPropertyChanged(nameof(CanLogin));
	}
}

위 코드는 Id가 변경된 후 Id와 연관된 bool 타입 CanLogin 속성의 변경도 함께 Notify합니다.

8개의 좋아요