퇴근5분전

데이타템플릿
 ListBox에 ToString() 말고, 임의의 모습으로 나타내고자 할때 사용할수 있음.

사용자 삽입 이미지
<DataTemplate으로 적용된 화면>


Window.xaml
<Window x:Class="OneTimeDataBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
    xmlns:myClass="clr-namespace:OneTimeDataBinding"
    Title="Window1" Height="236" Width="300" Loaded="Window_Loaded">
    <Window.Resources>
        <myClass:Code x:Key="cd" Name="_ResourceName" ></myClass:Code>

        <DataTemplate x:Key="dt" DataType="{x:Type myClass:Code}">
          <StackPanel Orientation="Horizontal">
             <TextBlock Text="{Binding Path=Name}" Foreground="Blue"></TextBlock>
             <TextBlock Text=":"></TextBlock>
             <TextBlock Text="{Binding Path=Age}" Foreground="Chartreuse"></TextBlock>               
            </StackPanel>
               
        </DataTemplate>    

    </Window.Resources>
    <Grid Height="289" x:Name="Grid1" DataContext="{StaticResource cd}">
        <Grid.RowDefinitions>
            <RowDefinition Height="65*" />
            <RowDefinition Height="224*" />
        </Grid.RowDefinitions>
        <TextBox Margin="12,12,73,10" Name="textBox1" Text="{Binding Path=Name}" />
        <Button HorizontalAlignment="Right" Margin="0,12,12,10" Name="button1" Width="55" Click="button1_Click">Button</Button>
        <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"
                  ItemTemplate="{StaticResource dt}" />
        </Grid>
    </Grid>
</Window>

Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.ComponentModel;

namespace OneTimeDataBinding
{
    /// <summary>
    /// Window1.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class Window1 : Window
    {
        Code cd = new Code();

        public Window1()
        {
            InitializeComponent();
            cd.Name = "초기 코드값";
            Grid1.DataContext = cd;
        }
      

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

        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; 
        }
    }

    ///// <summary>
    ///// 단일 바인딩 모델에서 사용한 클래스.
    ///// </summary>
    //public class Code
    //{
    //    string name = string.Empty;
    //    public string Name { get; set; }
    //}

    /// <summary>
    /// 코드 리스트
    /// </summary>
    public class CodeList : List<Code>
    {

    }


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

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

        int age = 0;

        public int Age { get { return age; } set { age = value; Update("Age"); } }


        #region INotifyPropertyChanged 멤버

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

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

        public override string ToString()
        {
            return name;
        }
    }

}

특정 객체에 저장된 데이타가 출력되는 화면을 정의하여 템플릿화 할수 있는데
이를 데이타 템플릿이라 한다.

ObservableCollection<T> : 책에 오타 있으므로 철자 주의!

위 소스에서 이전, 다음 버튼을 추가후 각각 버튼 처리를 한다.

// 이전
       private void button2_Click(object sender, RoutedEventArgs e)
        {
            ICollectionView view = CollectionViewSource.GetDefaultView(listBox1.DataContext);
            view.MoveCurrentToPrevious();
            if (view.IsCurrentBeforeFirst)  view.MoveCurrentToFirst();
            //Grid2.DataContext = view.CurrentItem as Code;
            listBox1.SelectedItem = view.CurrentItem;
        }
//다음
        private void button3_Click(object sender, RoutedEventArgs e)
        {
            ICollectionView view = CollectionViewSource.GetDefaultView(listBox1.DataContext);
            view.MoveCurrentToNext();
            if (view.IsCurrentAfterLast)  view.MoveCurrentToLast();
            //Grid2.DataContext = view.CurrentItem as Code;
            listBox1.SelectedItem = view.CurrentItem;
        }

이때 새로운 데이타 추가시~~ CodeList 가 변경 되는데 이때 컨트롤에 적용시키는 기능이 포함되어 있지 않다.

INotifyPropertyChanged 인터페이스가 List<T>에는 적용되어 있지 않아 갱신되지 않으므로
WPF에서는 이를 적용한 ObservableCollection<T> 제너릭컬렉션에 데이타를 저장하면 자동으로 갱신된다.

테스트 해보니 일반 List<T>를 사용하여 추가기능을 구현했을때는
추가후 ListBox에 추가된 Item은 보이지 않았음.

ObservableCollection<T>를 사용하여 구현하니 추가시 바로 갱신되는것을 확인하였음.

    public class oCodeList : ObservableCollection<Code>
    {    
    }

public class Window1 : Window
{
       ...

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            oCodeList cd = new oCodeList();
            // 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 button4_Click(object sender, RoutedEventArgs e)
        {
            oCodeList ls = listBox1.DataContext as oCodeList;
            //CodeList ls = listBox1.DataContext as CodeList;
            if (ls != null)
                ls.Add(new Code() { Name="add1", Age=ls.Count+1 });
        }
}

컨트롤 데이타 바인딩
 임의의 WPF 컨트롤에 설정된 데이타를 다른 컨트롤에 바인딩 할수도 있다.
이때 속성대 속성의 매칭을 통해 데이타의 이동이 발생한다.

간단히 바인딩 표현식이 바뀐다

<바인딩컨트롤
      Background="{Binding ElementName=대상컨트롤이름, Path=대상컨트롤속성이름}" ...
 />

책페이지 321부터 간략히 설명되있음...


me : 바인딩에 대해 2회로 나누어 확인하였음.
DataTemplate를 가지고 표시되는 형태를 마음대로 바꿀수 있다는 점이 역시 흥미로웠음.
다른부분은 .Net 2.0에서 코딩량이 좀 되지만 나름 구현이 가능했던 것들이라...
WPF에서의 바인딩 구현방법이 좀더 편하다는 생각이 들기도 했지만... 데이타 타입별로 Class화 해야된다면 파일또한 많아 지겠구나 싶었음. 필요하다면 지금까지 해왔던 방법대로 DataTable을 바인딩 걸어서 써보고 싶음.




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

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

툴을 제작 해서 프로젝트를... 진행하다!  (0) 2010.02.26
WPF 3D  (0) 2009.12.29
데이타바인딩(1)  (0) 2009.12.28
이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
컨트롤  (0) 2009.12.28