체휘
운동하는 개발자
체휘
전체 방문자
오늘
어제
  • 분류 전체보기
    • WPF
    • C#
    • C++
    • Python
    • 경제적 자유

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ResourceDictionary
  • binding
  • 경제 #인생 #목표
  • INotifyPropertyChanged
  • 레지스트리
  • WPF
  • style
  • async
  • ControlTemplate
  • border
  • ComboBox
  • singleton
  • 리소스
  • c#
  • ExpressionDark

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
체휘

운동하는 개발자

[WPF] - INotifyPropertyChanged를 이용한 Binding 방법
WPF

[WPF] - INotifyPropertyChanged를 이용한 Binding 방법

2023. 1. 1. 22:03

클래스 내부의 Property가 변경 되었을 때, 메인 컨트롤에 표시 될 수 있게 하는 바인딩 방법을 정리하였습니다.

 

순서대로 하나씩 정리해보겠습니다!

 

제가 테스트한 구조는 아래와 같습니다.(쉬운 이해를 위해 아래와 같이 구성하였습니다.)

1. MainWindow.xaml : 컨트롤을 생성하고 값을 표시하는 곳

2. MainWindow.xaml.cs : 버튼을 눌렀을 때, TestInfo 클래스 내부의 Property 값을 변경

3. Data.cs : Singleton 패턴이 적용된 Data 클래스

4. TestInfo.cs: Data 클래스를 통해 접근이 가능한 클래스, 이 클래스 내부에 Property가 들어있다.

 

MainWindow.xaml

<Window x:Class="WPF_Project.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Project"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Closed="Window_Closed">
    <Window.Resources>
        <Style x:Key="StdLabel" TargetType="Label">
            <Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
            <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
            <Setter Property="FontSize" Value="15"></Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Label x:Name="lbltest1" Content="{Binding TEST1}" Style="{StaticResource StdLabel}"></Label>
        <Label Grid.Row="1" x:Name="lbltest2" Content = "{Binding TEST2}" Style="{StaticResource StdLabel}"></Label>
        <Label Grid.Row="2" x:Name="lbltest3" Content = "{Binding TEST3}" Style="{StaticResource StdLabel}"></Label>
        <Label Grid.Row="3" x:Name="lbltest4" Content = "{Binding TEST4}" Style="{StaticResource StdLabel}"></Label>

        <Button Grid.Column="1" x:Name="btnValue" Margin="20" Click="btnValue_Click">Value 변경</Button>
    </Grid>
</Window>

Value변경 버튼을 누르면 TEST1, TEST2, TEST3, TEST4 속성이 변경되고 컨트롤에 표시되게 됩니다.

 

 

MainWindow.xaml.cs(작업코드)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Project
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

	//바인딩을 위해서는 DataContext에 객체를 등록해야합니다.
            this.DataContext = Data.Instance.Test;

	//TestInfo 클래스에서 PropertyChanged 이벤트가 발생하면 Test_PropertyChanged가 수행됩니다.
            Data.Instance.Test.PropertyChanged += Test_PropertyChanged;
        }

	//이벤트가 발생한 PropertyName에 따라서 출력합니다.
        private void Test_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if(e.PropertyName == "TEST1")
            {
                Console.WriteLine("1: {0}", Data.Instance.Test.TEST1);
            }
            else if (e.PropertyName == "TEST2")
            {
                Console.WriteLine("2: {0}", Data.Instance.Test.TEST2);
            }
            else if (e.PropertyName == "TEST3")
            {
                Console.WriteLine("3: {0}", Data.Instance.Test.TEST3);
            }
            else if (e.PropertyName == "TEST4")
            {
                Console.WriteLine("4: {0}", Data.Instance.Test.TEST4);
            }
        }

	//버튼을 클릭했을 때 값을 계속 변경하기 위한 기능
        int cnt = 0;
        private void btnValue_Click(object sender, RoutedEventArgs e)
        {
            Data.Instance.Test.TEST1 = string.Format("test{0}", cnt);
            Data.Instance.Test.TEST2 = string.Format("test{0}", cnt + 1);
            Data.Instance.Test.TEST3 = string.Format("test{0}", cnt + 2);
            Data.Instance.Test.TEST4 = string.Format("test{0}", cnt + 3);

            if(cnt == 50)
            {
                cnt = 0;
            }
            else
            {
                cnt++;
            }
        }

	//Window 종료 시 이벤트 해제
        private void Window_Closed(object sender, EventArgs e)
        {
            Data.Instance.Test.PropertyChanged -= Test_PropertyChanged;
        }
    }
}

 

Data.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace WPF_Project
{

    public class Data
    {
	//Singleton 패턴 적용
	//하나의 인스턴스만 사용하기 위한 패턴이다!
	//volatile은 컴파일러가 최적화하지 못하게 하는 것이다.
        private static object syncIns = new object();
        private static volatile Data instance;

        public static Data Instance
        {
            get
            {
                if(instance == null)
                {
                    lock(syncIns)
                    {
                        if(instance == null)
                        {
                            instance = new Data();
                        }
                    }
                }

                return instance;
            }
        }

        public Data()
        {

        }
        
	//TestInfo 클래스 선언
        private TestInfo testInfo = new TestInfo();
        public TestInfo Test
        {
            get
            {
                return testInfo;
            }
        }
    }
}

 

TestInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace WPF_Project
{
	//Property가 변경되었다는 것을 알리는 인터페이스 상속
    public class TestInfo : INotifyPropertyChanged
    {
    
	//PropertyChanged 이벤트 핸들러를 선언한다.
        public event PropertyChangedEventHandler PropertyChanged;

	//Property가 변경되었을 때 동기를 맞추기 위한 변수
        private static object syncIns = new object();

        private string test1 = string.Empty;
        public string TEST1
        {
            get
            {
                return test1;
            }
            set
            {
	//test1 값이 변경되었을 때, TEST1 속성 변경 이벤트 발생
                if (test1 != value)
                {
                    test1 = value;
                    OnPropertyChanged("TEST1");
                }
            }
        }

        private string test2 = string.Empty;
        public string TEST2
        {
            get
            {
                return test2;
            }
            set
            {
	//test2 값이 변경되었을 때, TEST2 속성 변경 이벤트 발생
                if (test2 != value)
                {
                    test2 = value;
                    OnPropertyChanged("TEST2");
                }
            }
        }

        private string test3 = string.Empty;
        public string TEST3
        {
            get
            {
                return test3;
            }
            set
            {
	//test3 값이 변경되었을 때, TEST3 속성 변경 이벤트 발생
                if (test3 != value)
                {
                    test3 = value;
                    OnPropertyChanged("TEST3");
                }
            }
        }

        private string test4 = string.Empty;
        public string TEST4
        {
            get
            {
                return test4;
            }
            set
            {
	//test4 값이 변경되었을 때, TEST4 속성 변경 이벤트 발생
                if (test4 != value)
                {
                    test4 = value;
                    OnPropertyChanged("TEST4");
                }
            }
        }
        
	//속성 값이 변경되었을 때, PropertyChanged 이벤트를 발생시킴
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                lock (syncIns)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
}

 

실행 프로그램


간단하게 바인딩이 적용되는 예제를 만들어 보았습니다.

 

많은 도움이 되길 바랍니다.

 

감사합니다.

 

'WPF' 카테고리의 다른 글

[WPF] - 리소스 적용하기  (0) 2023.01.03
[WPF] - Border  (0) 2022.12.31
[WPF] - Style, ControlTemplate  (0) 2022.12.31
[WPF] - ResourceDictionary 사용  (0) 2022.12.30
[WPF] - 프로젝트 생성 및 시작  (0) 2022.12.28
    'WPF' 카테고리의 다른 글
    • [WPF] - 리소스 적용하기
    • [WPF] - Border
    • [WPF] - Style, ControlTemplate
    • [WPF] - ResourceDictionary 사용
    체휘
    체휘
    항상 발전하는 개발자가 되고 싶습니다~

    티스토리툴바