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합니다.