독개

[WPF] 데이터바인딩 PropertyChanged 활용

by #독개#

 

데이터 바인딩에서 소스(데이터)객체는 UI 컨트롤 일수도 있지만, 소스 객체가 C#의 일반 클래스가 될 수 도 있다.

이 경우 프로퍼티(속성)의 값을 타겟(UI컨트롤의 속성)으로 받아 오는데,

아무때나 계속해서 받아오면 안되겠지 데이터(소스객체의 프로퍼티)가 변경될때만 바인딩 해와야 한다

즉 타겟 객체에 데이터가 변경되었음을 알릴 수 있는 매커니즘을 정의 해야한다

 

WPF 데이터 바인딩은 이벤트가 INotifyPropertyChanged 인터페이스를 구현한 클래스안에 정의되어 있으면

이벤트를 찾는데 데이터(소스객체의 프로퍼티값)의 변경을 알려주기 위해서는 이 인터페이스를 상속받아 구현하고

PropertyChangedEventHandler 델리게이트를 기본으로 하는 PropertyChanged 이벤트를 정의 해야한다

 

PropertyChanged 이벤트를 발생시킬 때의

처음인자는 this이고

두번째인자는 PropertyChangedEventArgs 타입의 객체이다

PropertyChangedEventArgs는 string타입의 PropertyName이라는 프로퍼티가 정의되어 있는데 프로퍼티를

구별하기 위해 사용한다. 그래서 PropertyChangedEventArgs를 new 하면서 프로퍼티 이름을 넣어준다

 

CallerMamberName(특성 Attribute)를 통해 어느 프로퍼티(속성)에서 PropertyChanged 이벤트가 발생했는지

확인 가능 합니다. 만약 CallerMemberName이 없으면 프로퍼티(속성) 이름을 문자열로 지정해야 한다

public void OnPopertyChanged([CallerMemeberName] string propertyname = null)
if(PropertyChanged != null)
{
	PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}

//PropertyChanged? Invoke(this, new PropertyChangedEventArgs(propertyname));
//위와 같이 줄일수 있다

위 방법이 다수의 프로퍼티를 다루는 좋은 방법 이다. 하나의 PropertyChanged 이벤트가 모든 프로퍼티에

대한 변경을 처리할 수 있기 때문이다

 

만일 이 PropertyChanged를 사용하지 않으면, 프로퍼티를 변경할때마다 this.DataContext=v;로 업데이트 해줘야 한다

PropertyChanged를 사용함으로써 우리는 프로퍼티의 값이 변경되면 자동으로 타겟(UI)의 속성으로 올려준다

일반적인 방법

namespace ViewModel
{
    public class ViewModelBase
    {
        public string tb1 { get; set; }
        public string tb2 { get; set; }
    }
}
        private void Button_Click1(object sender, RoutedEventArgs e)
        {
            ViewModel.ViewModelBase v = new ViewModel.ViewModelBase() { tb1 = "홍길동", tb2 = "심청이" };
            this.DataContext = v; //이때의 viewModel의 프로퍼티값으로 타겟에 올리기때문에 홍길동,심청이가 입력된다
            
            v.tb1 = "홍길동2";
            v.tb2 = "심청이2";
            //객체로 데이터를 주지 않는이상 프로퍼티에 아무리 다른값을 주더라도 타겟UI로 값을 전송하지 않는다
            //AHK에 gui,submit,nohide 이것과 같은개념 (this.DataContext = v 계속해줘야 업데이트된다)
        }

PropertyChanged 사용

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace ViewModel
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        private string _tb1;
        private string _tb2;

        public string Tb1
        {
            get => _tb1; set
            {
                _tb1 = value;
                OnPropertyChanged(); //CallerMemberName에 의해 자동으로 인자에 string Tb1이 들어간다
            }
        }

        public string Tb2
        {
            get => _tb2; set
            {
                _tb2 = value;
                OnPropertyChanged();
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }
        }
        //public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        //{
        //    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        //}
    }
}
using System.Windows;
using ViewModel;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            ViewModelBase v = new ViewModelBase() { Tb1 = "홍길동", Tb2 = "심청이" };
            this.DataContext = v;
        }

        private void Button_Click1(object sender, RoutedEventArgs e)
        {
            ViewModelBase v = this.DataContext as ViewModelBase;
            //따로 this.DataContext로 업데이트 해주지 않아도 프로퍼티의 값이 변경되었을 뿐인데 UI타겟을 변경 시킨다
            v.Tb1 = "홍길동2";
            v.Tb2 = "심청이2";
        }
    }
}

 

블로그의 정보

독한 개발자

#독개#

활동하기