프로그래밍

[WPF] WPF 일주일 만에 배우기 - WPF 데이터 바인딩

Victory_HA 2021. 6. 27. 17:40

 

4.1 데이터 바인딩

4.1.1 바인딩

  • xaml의 컨트롤의 속성에 CodeBehind에 있는 변수를 할당할 수 있다.
  • Text 속성은 데이터 객체의 Speed속성 값에 실제로 연결,
  • Speed속성이 TextBox 컨트롤의 Text속성에 초기 항당되면,
  • Text속성의 모든 변경(예를 들어 일부 값은 사용자가 입력)이 데이터 객체의 Speed 속성에 할당될 것이다.

Text 속성에 c객체의 Speed속성으로 초기화

<!-- Speed 는 속성 -->
<!-- c 는 객체 -->
<TextBox Text="{Binding Speed, ElementName= c}"/>
  • 아래 바인딩 예제에서 Slider 컨트롤의 값을 ProgressBar, TextBox에서 바인딩합니다.

 

바인딩 예제

<StackPanel Background="White">
    <Slider Maximum="100" Value="10" x:Name="slide" Height="30" Width="100" Margin="10" />
    <ProgressBar Value="{Binding Value, ElementName=slide}" Height="30" Width="100" Margin="10" />
    <TextBox Text="{Binding Value, ElementName=slide}" Height="30" Width="100" Margin="10" />
</StackPanel>

 

4.1.2 추가속성

  • 바인딩 표현식 내부에 여러 속성을 사용할 수 있다.

UpdateSourceTrigger

  • 입력 컨트롤 사용해 소스 속성이 업데이트되는 시기를 지정할 수 있다.
    • ex) UpdateSourceTrigger = PropertyChanged를 설정 하여 변경사항 발생 시, 원본 속성을 업데이트한다.

TargetNullValue

  • null로 해석될 때마다 원본 특성 값 대신 사용해야 하는 값을 지정한다.

FallbackValue

  • 문제 발생할 때마다 사용해야 하는 값을 지정한다.

StringFormat

  • 속성의 값에 포맷을 적용한다.

 

4.2 DataContext

  • 바인딩(ElementName, Source등을 사용)에 소스 데이터 객체를 지정하지 않으면, 소스가 현재 DataContext로 간주한다.
  • 아래 예제에서 DataContext="..." 부분을 생략하고 CodeBehind에 할당할 수 있다.

 

xaml

<StackPanel DataContext="...">
    <TextBox Text = "{Binding Name}"/>
    <Label Content="{Binding SSN}"/>
</StackPanel>

CodeBehind

this.DataContext = ...;
  • 실제로 모든 컨트롤은 Object유형의 DataContext 속성을 갖는다.
    • 즉, 모든 객체 유형을 DataContext에 할당 가능하다
  • 바인딩 식에 소스에 대한 언급이 없으면, 소스는 컨트롤의 DataContext 속성으로 간주된다.
  • DataContext가 할당되지 않으면(null 기본값), 부모 컨트롤의 DataContext가 사용된다.

4.3 변환기

(작성 예정)

4.4 목록 컨트롤을 사용하는 컬렉션 표시

(작성 예정)

4.5 목록 컨트롤 사용자 정의

  • ItemPanel : 요소를 배치하는 방법을 설명한다.
    • ItemPanel의 속성은 각 목록 항목에 대해 반복되는 DataTemplate이어야 한다.
    • DataTemplate 내부 요소는 데이터 바인딩 식을 사용해 해당 속성을 기본 항목 속성에 연결할 수 있다.
  • ItemTemplate : 각 요소에 대해 반복이 필요한 템플릿을 제공한다.
  • ItemContainerStyle : 항목을 선택하거나, 마우스를 올릴 때의 동작 방법을 설명한다.
  • Template : 컨트롤 자체를 렌더링 하는 방법을 설명한다.

 

사용예제

Talk.cs

using System; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Ink; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 
using System.Collections.ObjectModel;`

namespace BikeShop  
{  
    public class Talk : ObservableCollection  
    {  
        public Talk()  
        {  
            this.Add(new Message() { Sender = "Adventure Works", Content = "Hi, what can we do for you?" });  
            this.Add(new Message() { Sender = "Client", Content = "Did you receive the GR268 KZ bike?" });  
            this.Add(new Message() { Sender = "Adventure Works", Content = "Not yet, but we have a similar model available." });  
            this.Add(new Message() { Sender = "Client", Content = "What is it like?" });  
            this.Add(new Message() { Sender = "Adventure Works", Content = "It boasts a carbon frame, hydraulic brakes and suspension, and a gear hub." });  
            this.Add(new Message() { Sender = "Client", Content = "How much does it cost?" });  
            this.Add(new Message() { Sender = "Adventure Works", Content = "Same as the GR268 KZ model you requested. You can get it from our online shop." });  
            this.Add(new Message() { Sender = "Client", Content = "Thanks." });  
            this.Add(new Message() { Sender = "Adventure Works", Content = "Thank you, have a nice ride." });  
        }  
    }

    public class Message
    {
        public string Sender { get; set; }
        public string Content { get; set; }
    }
}

 

MainWindow.xaml

<Page x:Class="TEST0704.MainMenu"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:TEST0704"
      xmlns:e="clr-namespace:BikeShop"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="500"
      Title="MainMenu">

    <ListBox>
        <ListBox.ItemsSource>
            <e:Talk x:Name="talk"/>
        </ListBox.ItemsSource>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="chat.png" Width="20"/>
                        <TextBlock Text="{Binding Sender}"></TextBlock>
                    </StackPanel>
                    <TextBlock Text="{Binding Content}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Page>

 

결과

WpfApp1.zip
178.9 kB

 

4.8 INotifyPropertyChanged

  • WPF에서 Xaml파일은 View에 해당하고, cs파일은 ViewModel에 해당합니다.
  • ViewModel의 객체를 바인딩을 시켜서 View에 보여주게 되는데,
  • INotifyPropertyChanged는 바인딩된 값이 바뀔때마다 변하는 것을 인지해주어 백단의 값을 자동으로 바뀌게 해주는 역할을 합니다.
  • View 와 ViewModel의 값을 실시간으로 바꿔줍니다.

 

사용예제

  • Notifier.cs 클래스를 생성합니다.
  • CarProperty라는 ViewModel역할을 하는 클래스를 생성합니다.

 

Notifier.cs

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

namespace TEST0704  
{  
    public class Notifier : INotifyPropertyChanged      //속성 값이 변경되었음을 클라이언트에 알립니다.  
    {  
        public event PropertyChangedEventHandler PropertyChanged;        //속성 값이 변경될 때 이벤트 발생합니다.  

        protected void OnPropertyChanged(string propertyName)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

 

CarProperty.cs

 public class CarProperty : Notifier
    {
        private int _speed;
        public int Speed
        {
            get { return _speed; }
            set
            {
                _speed = value;
                //Speed 속성 명 값을 매개변수로 넣습니다.
                OnPropertyChanged("Speed");
            }
        }

        private string _color;
        public string Color
        {
            get { return _color; }
            set
            {
                _color = value;
                //Speed 속성 명 값을 매개변수로 넣습니다.
                OnPropertyChanged("Color");
            }
        }
    }