및 ObservableObject 인터페이스를 구현하여 관찰할 수 있는 개체의 INotifyPropertyChangedINotifyPropertyChanging 기본 클래스입니다. 속성 변경 알림을 지원해야 하는 모든 종류의 개체에 대한 시작점으로 사용할 수 있습니다.
플랫폼 API:
ObservableObject, ,TaskNotifierTaskNotifier<T>
작동 방식
ObservableObject 에는 다음과 같은 주요 기능이 있습니다.
-
INotifyPropertyChanged및INotifyPropertyChanging에 대한 기본 구현을 제공하고,PropertyChanged및PropertyChanging이벤트를 노출합니다. - 상속되는 형식
SetProperty에서ObservableObject속성 값을 쉽게 설정하고 적절한 이벤트를 자동으로 발생시키는 데 사용할 수 있는 일련의 메서드를 제공합니다. -
SetProperty와 유사하지만, 할당된 작업이 완료되면Task속성을 설정하고 알림 이벤트를 자동으로 발생시킬 수 있는SetPropertyAndNotifyOnCompletion메서드를 제공합니다. - 알림 이벤트가 발생하는 방식을 사용자 지정할 수 있도록 파생 형식에서 재정의할 수 있는
OnPropertyChanged및OnPropertyChanging메서드를 노출합니다.
단순 속성
다음은 사용자 지정 속성에 대한 알림 지원을 구현하는 방법의 예입니다.
public class User : ObservableObject
{
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
}
제공된 SetProperty<T>(ref T, T, string) 메서드는 속성의 현재 값을 확인하고 다른 경우 업데이트한 다음 관련 이벤트도 자동으로 발생합니다. 속성 이름은 특성을 사용하여 [CallerMemberName] 자동으로 캡처되므로 업데이트할 속성을 수동으로 지정할 필요가 없습니다.
관찰 불가능한 모델 감싸기
예를 들어 데이터베이스 항목을 사용할 때 일반적인 시나리오는 데이터베이스 모델의 속성을 릴레이하고 필요할 때 속성 변경 알림을 발생시키는 래핑 "바인딩 가능" 모델을 만드는 것입니다. 인터페이스를 구현 INotifyPropertyChanged 하지 않는 모델에 알림 지원을 삽입하려는 경우에도 필요합니다.
ObservableObject 는 이 프로세스를 더 간단하게 만드는 전용 메서드를 제공합니다. 다음 예제에서 User은 ObservableObject을 상속하지 않고 데이터베이스 테이블에 직접 매핑되는 모델입니다.
public class ObservableUser : ObservableObject
{
private readonly User user;
public ObservableUser(User user) => this.user = user;
public string Name
{
get => user.Name;
set => SetProperty(user.Name, value, user, (u, n) => u.Name = n);
}
}
이 경우에는 SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string) 오버로드를 사용하고 있습니다. 서명은 이전 시나리오보다 약간 더 복잡합니다. 이전 시나리오와 같이 지원 필드에 액세스할 수 없더라도 코드가 여전히 매우 효율적일 수 있도록 해야 합니다. 이 메서드 서명의 각 부분을 자세히 살펴보고 다양한 구성 요소의 역할을 이해할 수 있습니다.
-
TModel는 래핑할 모델의 형식을 나타내는 형식 인수입니다. 이 경우 클래스User가 됩니다. 이를 명시적으로 지정할 필요가 없습니다. C# 컴파일러는 메서드를 호출하는SetProperty방법에 따라 이를 자동으로 유추합니다. -
T은 설정하려는 속성의 형식입니다.TModel와 마찬가지로 이것도 자동으로 추론됩니다. -
T oldValue는 첫 번째 매개 변수이며, 이 경우 래핑하는 해당 속성의 현재 값을 전달하는 데 사용합니다user.Name. -
T newValue는 속성으로 설정할 새 값이며, 여기서는 속성 setter 내의 입력 값인 전달value합니다. -
TModel model는 래핑할 대상 모델이며, 이 경우user필드에 저장된 인스턴스를 전달합니다. -
Action<TModel, T> callback는 속성의 새 값이 현재 값과 다르고 속성을 설정해야 하는 경우 호출되는 함수입니다. 이 작업은 대상 모델 및 설정할 새 속성 값을 입력으로 수신하는 이 콜백 함수에 의해 수행됩니다. 이 경우에는 입력값(이를n라고 부름)을Name속성에 할당합니다(u.Name = n를 수행하여). C# 컴파일러가 콜백 함수를 캐시하고 여러 가지 성능 향상을 수행할 수 있으므로 현재 범위에서 값을 캡처하지 않고 콜백에 대한 입력으로 지정된 값과만 상호 작용하는 것이 중요합니다. 이 때문에 여기서user필드나 setter의value매개변수에 직접 접근하는 것이 아니라, 대신 람다 식의 입력 매개변수만 사용합니다.
이 SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string) 메서드는 매우 간단한 API를 제공하면서 대상 속성을 검색하고 설정하는 것을 모두 처리하므로 이러한 래핑 속성을 매우 간단하게 만듭니다.
참고
LINQ 식을 사용하는 이 메서드의 구현과 비교할 때, 특히 상태 및 콜백 매개 변수 대신 형식 Expression<Func<T>> 의 매개 변수를 통해 이러한 방식으로 달성할 수 있는 성능 향상은 매우 중요합니다. 특히 이 버전은 LINQ 식을 사용하는 버전보다 ~200배 빠르며 메모리 할당을 전혀 수행하지 않습니다.
Task<T> 속성 처리
속성이 Task 면 작업이 완료되면 알림 이벤트를 발생시켜 바인딩이 적시에 업데이트되도록 해야 합니다. 예를 들어 태스크가 나타내는 작업에 로드 표시기 또는 기타 상태 정보를 표시합니다.
ObservableObject 이 시나리오에 대한 API가 있습니다.
public class MyModel : ObservableObject
{
private TaskNotifier<int>? requestTask;
public Task<int>? RequestTask
{
get => requestTask;
set => SetPropertyAndNotifyOnCompletion(ref requestTask, value);
}
public void RequestValue()
{
RequestTask = WebService.LoadMyValueAsync();
}
}
SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string) 여기서 메서드는 대상 필드 업데이트, 새 작업 모니터링( 있는 경우) 및 해당 작업이 완료될 때 알림 이벤트를 발생시키는 작업을 처리합니다. 이렇게 하면 작업 속성에 바인딩하고 상태가 변경될 때 알림을 받을 수 있습니다.
ObservableObject에서 노출되는 TaskNotifier<T>는 대상 Task<T> 인스턴스를 래핑하고 이 메서드에 필요한 알림 논리를 지원하는 특수한 형식입니다. 일반 Task만 있는 경우에도 TaskNotifier 유형을 직접 사용할 수 있습니다.
참고
메서드 SetPropertyAndNotifyOnCompletion는 Microsoft.Toolkit 패키지의 NotifyTaskCompletion<T> 형식 사용을 대체하기 위한 것입니다. 이 형식을 사용 중인 경우 내부 Task (또는 Task<TResult>) 속성으로 바꿀 수 있으며 SetPropertyAndNotifyOnCompletion 메서드를 사용하여 값을 설정하고 알림 변경을 발생할 수 있습니다.
NotifyTaskCompletion<T> 형식에서 노출하는 모든 속성은 Task 인스턴스에서 직접 사용할 수 있습니다.
예제
- 샘플 앱(여러 UI 프레임워크의 경우)을 확인하여 작동 중인 MVVM 도구 키트를 확인합니다.
- 단위 테스트에서 더 많은 예제를 찾을 수도 있습니다.
MVVM Toolkit