티스토리 뷰

반응형

우리는 MVVM을 위해 다음처럼 복잡한 INotifyPropertyChanged 코드를 매번 작성해야 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class UserViewModel : INotifyPropertyChanged
{
    private string _UserName;
    public string UserName { get => _UserName; set => SetProperty(ref _UserName, value); }
 
    private DateTime? _BirthDate;
    public DateTime? BirthDate { get => _BirthDate; set => SetProperty(ref _BirthDate, value); }
 
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
    public void SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (storage?.Equals(value) == true)
            return;
        storage = value;
        OnPropertyChanged(propertyName);
    }
}

PropertyChanged.Fody 패키지를 사용하면 위의 코드를 아래와 같이 간략하게 작성할 수 있게 됩니다.

1
2
3
4
5
6
7
public class UserViewModel : INotifyPropertyChanged
{
    public string UserName { get; set; }
    public DateTime? BirthDate { get; set; }
 
    public event PropertyChangedEventHandler PropertyChanged;
}

PropertyChanged.Fody 패키지

PropertyChanged.Fody 패키지는 Code Generator로서, 컴파일이 진행되는 동안 INotifyPropertyChanged 구현 클래스를 찾아 MVVM 코드를 완성시켜줍니다. 다음과 같이 패키지 추가 후 간단히 사용할 수 있습니다.

  1. Visual Studio의 Nuget Package Manager에서 PropertyChanged.Fody 패키지를 설치해주세요.
    Nuget Package Manager
  2. 프로젝트에 FodyWeavers.xml 파일을 추가하고 아래와 같이 작성해주세요.
    1
    2
    3
    <Weavers>
      <PropertyChanged/>
    </Weavers>
  3. 이제 INotifyPropertyChanged 클래스를 작성하기만 하면됩니다.
    1
    2
    3
    4
    5
    6
    7
    8
    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
         
        public string GivenNames { get; set; }
        public string FamilyName { get; set; }
        public string FullName => $"{GivenNames} {FamilyName}";
    }
    혹은 [ImplementPropertyChanged] Attribute를 추가하기만 해도 됩니다.
    1
    2
    3
    4
    5
    6
    7
    [ImplementPropertyChanged]
    public class Person
    {
        public string GivenNames { get; set; }
        public string FamilyName { get; set; }
        public string FullName => $"{GivenNames} {FamilyName}";
    }
  4. 컴파일이 진행될 때 아래와 같이 구현을 완성시켜줍니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
     
        string givenNames;
        public string GivenNames
        {
            get => givenNames;
            set
            {
                if (value != givenNames)
                {
                    givenNames = value;
                    OnPropertyChanged(InternalEventArgsCache.GivenNames);
                    OnPropertyChanged(InternalEventArgsCache.FullName);
                }
            }
        }
     
        string familyName;
        public string FamilyName
        {
            get => familyName;
            set
            {
                if (value != familyName)
                {
                    familyName = value;
                    OnPropertyChanged(InternalEventArgsCache.FamilyName);
                    OnPropertyChanged(InternalEventArgsCache.FullName);
                }
            }
        }
     
        public string FullName => $"{GivenNames} {FamilyName}";
     
        protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
        {
            PropertyChanged?.Invoke(this, eventArgs);
        }
    }
     
    internal static class InternalEventArgsCache
    {
        internal static PropertyChangedEventArgs FamilyName = new PropertyChangedEventArgs("FamilyName");
        internal static PropertyChangedEventArgs FullName = new PropertyChangedEventArgs("FullName");
        internal static PropertyChangedEventArgs GivenNames = new PropertyChangedEventArgs("GivenNames");
    }

Notify를 원하지 않는 Property가 있다면 아래와 같이 Attribute를 추가해주세요.

1
2
[DoNotNotify]
public string UserName { get; set; }

같이 Notify 되어야할 Property가 있다면 아래와 같이 작성하실 수 있습니다.

1
2
[AlsoNotifyFor("Age")]
public DateTime BirthDate { get; set; }

References

이외에도 다양한 추가기능을 제공합니다. 자세한 사항은 Fody Github 사이트를 참고해주세요.
- https://github.com/Fody/PropertyChanged)

댓글