퇴근5분전

데이타 바인딩 모델
  1. 단일         : 읽기전용 바인딩 모델
  2. 단방향      : 읽기전용 바인딩 모델 & 저장소데이타 변경시 자동 변경
  3. 양방향      : 읽기/쓰기 바인딩 모델

- 단일
  데이타를 값 대입해주는 형태로 사용함.( 기존 Form작업시 많이 사용했음. )
 컨트롤.프로퍼티 = 저장소.프로퍼티;

- 단방향
  객체의 상태변화를 이용해서 변경시 자동으로 바인딩된 컨트롤에 반영되도록 해주는 모델
  -- 객체 상태 변화
   객체의 상태변화시 System.ComponentModel.INotifyPropertyChanged 를 이용하여 제어가 가능하다.
 
    /// <summary>
    /// 단방향 모델에서 사용한 클래스.
    /// </summary>
    public class Code : INotifyPropertyChanged
    {
        string name = string.Empty;
        public string Name { get { return name; } set { name = value; Update("Name"); } }

        #region INotifyPropertyChanged 멤버
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        public void Update(string PropertyName)
        {
            if( PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
 
   이렇게 인터페이스를 구현하고 윈도우폼 상에서 이벤트를 정의 하여 객체 변화 시
  데이타를 갱신해주는 형태로 구현이 된다.

책에는 양방향 언급이 초반에 살짝 있고 사라졌다...
대신 바인딘 표현식 이란것으로 대체 한듯한데...

바인딩 표현식
           Code cd = new Code();
           cd.Name = "초기 코드값";
           textBox1.DataContext = cd;  // 데이타 원본 할당
데이타를 컨트롤에 바인딩 하고
<TextBox  Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
컨트롤 프로퍼티에 바인딩되는 데이타객체의 프로퍼티를 지정하여 결정한다.



바인딩 방향에 대한 문제는 저장소 객체 -> 데이타표출컨트롤 쪽에 해당하는 문제인듯 함.
이유:
 테스트 해본결과
    1. 저장소객체와 컨트롤을 바인딩 : <... Text="{Binding Path=Name}" />
    2. 저장소객체의 프로퍼티를 이용한 데이타 변경 :  데이타 표출컨트롤 반영 안됨.
    3. 데이타표출컨트롤에서 값 변경 : 저장소객체 데이타변경되있음.

private void UpdateBtn_Click(object sender, RoutedEventArgs e)
{
      cd.Name = "변경 값";                  
}

일때

    /// <summary>
    /// 단방향 모델에서 사용한 클래스.
    /// </summary>
    public class Code : INotifyPropertyChanged
    {
        string name = string.Empty;

        public string Name { get { return name; } set { name = value; Update("Name"); } }

        #region INotifyPropertyChanged 멤버

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public void Update(string PropertyName)
        {
            if( PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));       // -----①
        }
    }

따로 Code객체에 PropertyChanged 에 이벤트핸들러를 추가하지 않고 있으나

① 이 주석여부에 따라~!!!  표출컨트롤에 데이타 갱신이 일어나는것으로 보아
 바인딩 될때 내부적으로 PropertyChanged 이벤트에 핸들러를 추가하는듯 함.

의존 속성 ( Dependency Property )
 
Window.xaml
 <Grid Height="48" x:Name="Grid1">
        <TextBox Height="23" Margin="12,12,73,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
        <Button Height="23" HorizontalAlignment="Right" Margin="0,12,12,0" Name="button1" VerticalAlignment="Top" Width="55" Click="button1_Click">Button</Button>
    </Grid>

Window.xaml.cs
        Code cd = new Code();
        public Window1()
        {
            InitializeComponent();
            cd.Name = "초기 코드값";
            Grid1.DataContext = cd;
        }
 
위와 같이 TexBox에 바인딩 표현식이 존재하나 실제 바인딩 원본은 Grid1.DataContext 에 바인딩 되어있을시  그리드에 하위 요소인 TextBox에서는 자신에게 바인딩된 원본이 없으므로 상위 객체에서 바인딩원본을 찾게 된다. 이때 Text 가 곧 의존 속성이 된다. ( 이해한대로 썼음... )


선언적 데이타 원본

<Window.Resources>
   <Code x:Key="cd" xmlns="clr-namespace:OneTimeDataBinding" Name="_ResourceName" ></Code>
</Window.Resources>
   <Grid Height="48" x:Name="Grid1" DataContext="{StaticResource cd}">
        <TextBox Height="23" Margin="12,12,73,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
        <Button Height="23" HorizontalAlignment="Right" Margin="0,12,12,0" Name="button1" VerticalAlignment="Top" Width="55" Click="button1_Click">Button</Button>
    </Grid>

이런식으로 되있다.

<Code> 는 컴파일시 Code 객체로 변환되고 그리드에 바인딩하고 TextBox는 의존속성에 의해 그리드에 원본데이타를 표시하게 됨.

선언적이란건 리소스에 데이타원본을 선언한다라는 의미인듯 하다.


다중 데이타 바인딩
 리스트 박스 같은 여러개의 객체를 바인딩 할때...

List를 이용하고 ToString을 재정의 하고, 의존속성을 이용하고 하니 간편하게 코딩이 가능하다눈...

책에 300페이지 ~ 307페이지 내용인데.

Window.xaml.cs
 private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CodeList cd = new CodeList();
            cd.Add(new Code() { Name = "Code1", Age=1});
            cd.Add(new Code() { Name = "Code2", Age=2 });
            cd.Add(new Code() { Name = "Code3", Age=3 });

            listBox1.DataContext = cd;
        }

        private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Grid2.DataContext = e.AddedItems; 
        }

Window.xaml
 <Grid Name="Grid2" Margin="0,12,0,100" Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="132*" />
                <ColumnDefinition Width="146*" />               
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="89.473*" />
                <RowDefinition Height="23.527*" />
            </Grid.RowDefinitions>
            <TextBlock Text="{Binding Path=Name}" Margin="12,0,12,6" Grid.Row="1" Height="17.527" VerticalAlignment="Bottom"></TextBlock>
            <TextBlock Text="{Binding Path=Age}" Margin="12,0,26,10" Grid.Row="1" Grid.Column="1" Height="13.527" VerticalAlignment="Bottom"></TextBlock>
            <ListBox Margin="12,6,0,6" Name="listBox1" ItemsSource="{Binding}" Grid.ColumnSpan="2" HorizontalAlignment="Left" Width="260" SelectionChanged="listBox1_SelectionChanged" />
        </Grid>



꾀 길어졌는데 잘라볼까낭..

- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

WPF 3D  (0) 2009.12.29
데이타바인딩(2)  (0) 2009.12.28
이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
컨트롤  (0) 2009.12.28
스타일  (0) 2009.12.26