PropertyChangeNotification
OneWay 또는 TwoWay 바인딩을 지원하여 바인딩 대상 속성이 자동으로 바인딩 소스의 동적 변경 사항을 반영 하도록 하려면 클래스가 적절한 속성 변경 알림을 제공하는 INotifyPropertyChanged 또는 ObservableCollection<T>를 상속받아 구현해야 합니다.
이번 예제는 ItemsControl을 이용해 컬렉션을 표현하며, DataTemplate를 이용해 항목의 모양을 설정 합니다. 컬렉션 개체는 타이머를 통해 속성 값을 주기적으로 업데이트 하고 바인딩 된 값이 UI에 반영되는 것을 볼 수 있습니다.
- INotifyPropertyChanged를 구현하는 클래스를 정의 합니다.
1: public class Bid : INotifyPropertyChanged
2: {
3: private string _bidItemName;
4: private decimal _bidItemPrice;
5: public string BidItemName
6: {
7: get { return _bidItemName; }
8: set
9: {
10: if (_bidItemName != value)
11: {
12: _bidItemName = value;
13: // 속성이 업데이트 될 때마다 OnPropertyChanged를 호출합니다.
14: OnPropertyChanged("BidItemName");
15: }
16: }
17: }
18: public decimal BidItemPrice
19: {
20: get { return _bidItemPrice; }
21: set
22: {
23: if (_bidItemPrice != value)
24: {
25: _bidItemPrice = value;
26: // 속성이 업데이트 될 때마다 OnPropertyChanged를 호출합니다.
27: OnPropertyChanged("BidItemPrice");
28: }
29: }
30: }
31: public Bid(string newBidItemName, decimal newBidItemPrice)
32: {
33: _bidItemName = newBidItemName;
34: _bidItemPrice = newBidItemPrice;
35: }
36: // 이벤트 선언
37: public event PropertyChangedEventHandler PropertyChanged;
38: // OnPropertyChanged를 통해 바인딩에서 속성 값을 업데이트합니다.
39: protected void OnPropertyChanged(string propertyName)
40: {
41: PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
42: }
43: }
- ObservableCollection<T>를 구현하는 클래스를 정의 하고, 타이머를 등록하여 일정 시간 마다 BidItemPrice 속성 값을 변경하도록 합니다.
1: public class BidCollection : ObservableCollection<Bid>
2: {
3: private readonly Bid _item1 = new Bid("Perseus Vase", (decimal)24.95);
4: private readonly Bid _item2 = new Bid("Hercules Statue", (decimal)16.05);
5: private readonly Bid _item3 = new Bid("Odysseus Painting", (decimal)100.0);
6: public BidCollection()
7: {
8: Add(_item1);
9: Add(_item2);
10: Add(_item3);
11: CreateTimer();
12: }
13: private void CreateTimer()
14: {
15: var timer1 = new System.Timers.Timer
16: {
17: Enabled = true,
18: Interval = 2000
19: };
20: timer1.Elapsed += Timer1_Elapsed;
21: }
22: private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
23: {
24: _item1.BidItemPrice += (decimal)1.25;
25: _item2.BidItemPrice += (decimal)2.45;
26: _item3.BidItemPrice += (decimal)10.55;
27: }
28: }
- 사용자 정의 컬렉션을 로컬 리소스로 선언 하여 ItemsControl의 ItemSource로 사용 합니다. DataTemplate을 이용해 사용자 지정 항목 모양을 지정합니다.
1: <Window.Resources>
2: <local:BidCollection x:Key="MyDataSource" />
3: <DataTemplate x:Key="BidItemDataTemplate">
4: <Canvas Width="300" Height="20">
5: <TextBlock FontSize="14" Foreground="DarkSlateGray" Width="180" Canvas.Left="0" Text="{Binding Path=BidItemName}" />
6: <TextBlock FontSize="14" Foreground="DarkSlateBlue" Text="$" Canvas.Left="180" />
7: <TextBlock FontSize="14" Foreground="DarkSlateBlue" Width="80" Canvas.Left="190" Text="{Binding Path=BidItemPrice}" />
8: </Canvas>
9: </DataTemplate>
10: </Window.Resources>
- Resource를 ItemsControl의 ItemsSource 속성과 ItemTempalte 속성에 바인딩 합니다.
1: <DockPanel Width="350" Height="150">
2: <TextBlock FontSize="18" Margin="5" FontWeight="Bold" FontFamily="Verdana" DockPanel.Dock="Top">My Auction Tracker</TextBlock>
3: <ItemsControl Name="MyListBox" DockPanel.Dock="Top" Background="Silver" Width="315" Height="80"
4: ItemsSource="{Binding Source={StaticResource MyDataSource}}"
5: ItemTemplate="{StaticResource BidItemDataTemplate}" />
6: </DockPanel>
App을 실행하면 타이머가 갱신되어 속성 값이 변경 될 때마다 UI의 값도 자동으로 갱신되는 것을 보실 수 있습니다.
댓글
댓글 쓰기