티스토리 뷰

반응형

What is target and what is source?


In WPF,
여러분은 일반적으로 두 객체간에 연결고리를 지으려고 할때 데이타 바인딩을 사용할 겁니다.
한 객체는 source를 참조하고, 한 객체는 target을 참조하지요.
대부분 일반적인 시나리오에는
여러분의 소스 객체는 데이타와 그 데이타를 표현하는 타켓 컨트롤 개체를 포함하는 객체입니다.
(에쒸...뭔소리야...)
(그니까 내 소스 객체 > 타켓 컨트롤 객체 > 데이타)

예를 들어보자,
"이름" 속성을 가진 "사람"이라는 클래스가 있다고 생각하자
화면에 이름 값이 출력되고,
내가 속성창에서 이름값을 변경하거나, 프로그램 실행중 값을 변경하면 그또한 자동으로 변경되는걸 원한다.
TextBox 클래스의 Text 객체가
"사람" 클래스의 "이름" 객체이다.

 

<Window

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:BindingSample">

 

  <Window.Resources>

    <!-- Instantiates the Person class with the Name value "Joe"-->

    <!-- Giving it an x:Key so it's available as a resource -->

    <local:Person x:Key="myDataSource" Name="Joe"/>

  </Window.Resources>

 

  <!-- Binding the Text property to the Name property -->

  <TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>

 

</Window>

 

자, 이러한 예로들면:

  • TextBlock 는 target 객체
  • Text 속성은 target 속성
  • Person 객체는 source 객체
  • Name 속성은 source 속성



어떨때 Source를 사용하고 어떨때 DtaContext를 사용하는가?

데이터가 어떻게 오냐에 따라서 다양한 바인딩 방법이 있습니다.
Source속성으로 바인딩하는 XAML로 예를 들어보죠

 

Source 속성은 읽기쉽고 간단합니다.
하지만, 똑같은 소스를 다른 속성으로 바인딩을 더해야 할때는 문제가 생기죠
이럴때는 DataContext 속성을 써야 합니다.
DataContext 속성은 데이타 범위를 구분하는데 효과적입니다.
바인딩해야할 컨트롤은 많고 소스는 같을때 아래와 같은 방법을 써보세요.

 

<Window . . .>

  <Window.Resources>

    <local:Person x:Key="myDataSource" Name="Joe"/>

  </Window.Resources>

 

  <StackPanel>

    <StackPanel.DataContext>

      <Binding Source="{StaticResource myDataSource}"/>

    </StackPanel.DataContext>

 

    <TextBox Text="{Binding Path=Name}"/>

    <TextBlock Text="{Binding Path=Name}"/>

    <!-- ...

         Other controls that are also

         interested in myDataSource.

         ...

    -->

  </StackPanel>

</Window>

 

텍스트박스는 값이 변할때 업데이트를 어떻게 할까?

일반적으로 TextBox.Text has 는 포커스를 잃을때 UpdateSourceTrigger 속성이 발생합니다.
즉, 포커스를 잃지 않으면 UpdateSourceTrigger  속성도 이벤트가 안생기고, 업데이트는 없다는 말이죠.
그럼 UpdateSourceTrigger 속성을 바꾸면 업데이트가 되겠군요.
 

    <TextBox Text="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"/>

 

이 표는 UpdateSourceTrigger 가 텍스트박스에서 제공하는 방법들을 보여줍니다.
기억하세요 TextBox.Text 속성안에서만 쓰이는 거에요.

 

UpdateSourceTrigger value

When the Source Value Gets Updated

Example Scenario for TextBox

LostFocus (default for TextBox.Text)

When the TextBox control loses focus

A TextBox that is associated with validation logic

PropertyChanged

As you type into the TextBox

TextBox controls in a chat room window

Explicit

When the application calls UpdateSource

TextBox controls in an editable form (updates the source values only when the user clicks the submit button)

 

 

무슨말이지 OneWay?  TwoWay? 바인딩

음..간단하게 말하면
OneWay 모드는 read-only(읽기전용) 이고
TwoWay 모드는 read-write(읽기쓰기) 입니다.

재고 관리 프로그램을 예로 들면,
일반적으로 보여주기만 하는 컨트롤들로만 구성하여 만들 수도 있고(OneWay)
수량을 수정하고, 관리하는 동시기능을 구축할수도 있죠(TwoWay)

UpdateSourceTrigger 도 비슷합니다.
TextBox.Text, ComboBox.Text, MenuItem.IsChecked, 등등의 User-editable  속성은
TwoWay 모드 방식입니다.

 

내가 만든 객체는 값이 바껴도 새로운 값으로 바인딩을 하지 않아요!!

여러분이 만든 객체는 속성이 변할때 알려주는 이벤트 기능이 필요하군요.
INotifyPropertyChanged 가 바로 그것이지요.

using System.ComponentModel;

 

namespace BindingSample

{

  public class Person : INotifyPropertyChanged

  {

    private string name;

    // Declare the event

    public event PropertyChangedEventHandler PropertyChanged;

 

    public Person()

    {

    }

 

    public Person(string value)

    {

        this.name = value;

    }

     

    public string Name

    {

      get { return name; }

      set

      {

        name = value;

        // Call OnPropertyChanged whenever the property is updated

        OnPropertyChanged("Name");

      }

    }

 

    // Create the OnPropertyChanged method to raise the event

    protected void OnPropertyChanged(string name)

    {

      PropertyChangedEventHandler handler = PropertyChanged;

      if (handler != null)

      {

        handler(this, new PropertyChangedEventArgs(name));

      }

    }

  }

}


프로퍼티는 반드시 public이어야 하고, 필드 자체를 바인딩 할 순 없다는걸 명심하세요.

 

 

바인딩 코드는 어떻게 만들어요?

target 객체이 있는 SetBinding 메소드로 합니다.

Person myDataSource = new Person("Joe");     

Binding myBinding = new Binding("Name");

myBinding.Source = myDataSource;

// myText is an instance of TextBlock

myText.SetBinding(TextBlock.TextProperty, myBinding);

 

오직 FrameworkElements 와 FrameworkContentElements 에서만 SetBinding 메소드가 있습니다
정확히 말하면 BindingOperations.SetBinding 메소드입니다.

 

 

객체가 이미 초기화 되어 있을때는 어떻게 바인딩 하나요?

여태까지는 런타임시 객체를 초기화하여 바인딩 하였습니다.
그렇다면 이미 초기화 되어 있다면? 아마도 DataContext 속성이 필요하겠지요?
 

      // myListBox is a ListBox control

      // myCustomBizObject is your custom business object

      myListBox.DataContext = myCustomBizObject;

 

여기 두가지 방법이 있습니다.
첫번째로 같은 영역에 다른 요소에 바인딩하는 것

      <ComboBox Name="myComboBox" SelectedIndex="0">

        <ComboBoxItem>1</ComboBoxItem>

        <ComboBoxItem>2</ComboBoxItem>

        <ComboBoxItem>3</ComboBoxItem>

      </ComboBox>

      <TextBlock Text="{Binding ElementName=myComboBox, Path=SelectedItem.Content}"/>

 

두번째로 속성이 같은 컨트롤에 바인딩 하는 것
RelativeSource={x:Static RelativeSource.Self}.



질답으로 이어진 이번 포스트는 많이 어려웠네요 꺄악!
다음번에 또 한대요...아 .....
이번 포스트야 말로 내맘대로 번역이었으니

잘못 해석된 내용을 읽고 이해해 버렸다면 그건 당신의 실수!!! 우후훘~!


- Tina 씀

반응형
댓글