Part5. Using the ListBox and DataBinding to Display List Data
u Understand DataBinding
1. 데이터 바인딩의 개념
- 우선, UI 엘레먼트와 데이터 개체와의 연결을 만드는 과정이라고 보시면 됩니다.
- 바인딩 원본 개체의 특정 속성이 바인딩대상 엘리먼트의 의존 속성과 다르거나 원본 개체 속성의 값이 가공해야 할 경우 변환기(ValueConverter)를 통해 변경해야 합니다.
- 데이터 바인딩 기본 개념도
※ 데이터 바인딩의 장점
- 모든 개체들의 속성(Property)이 바인딩을 지원합니다.
- 데이터 템플릿과 스타일을 통해 데이터표현이 자유롭고 유연합니다.
- UI로 부터 비즈니스 로직을 완벽히 분리할 수 있습니다.
2. 데이터 흐름
- BindingMode열거형
속성 |
설명 |
OneWay |
바인딩이 만들어지거나 바인딩 원본 개체 속성이 변경되었을 때 바인딩 대상 개체의 속성 값을 변경합니다. |
OneTime |
바인딩이 만들어질 때만 바인딩 대상 개체의 속성 값을 변경합니다. |
TwoWay |
바인딩 원본과 대상 개체의 속성 중 하나가 변경되면 나머지 하나의 속성 값을 변경합니다. |
- OneWay, TwoWay와 같이 바인딩 원본 개체의 속성값이 변경되었을 때 대상 개체의 속성값을 변경하기 위해서는 INotifyPropertyChanged 인터페이스를 구현해야만 합니다.
3. 데이터 바인딩 표현식
<object Property=”{Binding}” …/> <object Property=”{Binding propertyPath}” …/> <object Property=”{Binding oneOrMoreBindingProperties}” …/> <object Property=”{Binding propertyPath , oneOrMoreBindingProperties }” …/> |
u Sample Code
1. 마우스 왼쪽 버튼 클릭 이벤트로 TextBlock 색깔 바꾸기
- 텍스트 블록에 Foreground 데이터 바인딩하기
Code
Page.xaml <UserControl x:Class="DemoSample2.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White" > <TextBlock x:Name="TextBlock1" Margin="10" Foreground="{Binding ChangingColor}">DataBinding Sample Code</TextBlock> </Grid> </UserControl> Page.xaml.cs using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace DemoSample2 { public partial class Page : UserControl { MyColors myColor = new MyColors(); public Page() { InitializeComponent(); myColor.ChangingColor = new SolidColorBrush(Colors.Red); this.TextBlock1.DataContext = myColor; } } public class MyColors { private SolidColorBrush changingColor; public SolidColorBrush ChangingColor { get { return changingColor; } set { changingColor = value; } } } } |
Description
ð Page.xaml 텍스트 블록의 Foreground 속성에 바인딩합니다.
ð 데이터 바인딩을 위한 원본 개체를 만들기 위해 MyColors 클래스를선언하였습니다.
ð Page()에서 Object 개체에 데이터 바인딩을 지정하였습니다.
Result
- 마우스 왼쪽 버튼 클릭 이벤트 추가
Code
Page.xaml <TextBlock x:Name="TextBlock1" Margin="10" Foreground="{Binding ChangingColor}" MouseLeftButtonDown="TextBlock1_MouseLeftButtonDown">DataBinding Sample Code</TextBlock> Page.xaml.cs private void TextBlock1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { myColor.ChangingColor = new SolidColorBrush(Colors.Black); } |
Description
ð 마우스 왼쪽 버튼 클릭 이벤트를 추가하였습니다. 빌드 후, 결과 화면을 보시면, 상단 이미지와 동일하게 텍스트 블록 색깔 변화가없는 것을 볼 수 있습니다.
ð 속성 값 변경을 감지해서 대상 속성의 값을 변경하기 위해서는INotifyPropertyChanged 인터페이스를 반드시 구현해 주어야 합니다.
- INotifyPropertyChanged인터페이스 구현
Code
public class MyColors : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private SolidColorBrush changingColor; public SolidColorBrush ChangingColor { get { return changingColor; } set { changingColor = value; NotifyPropertyChaged("ChangingColor"); } } private void NotifyPropertyChaged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } |
2. ListBox컨트롤에 DataBinding 하기
- Part3.“Naver OpenAPI 를 이용한 Book검색” 코드에서 DataGrid 컨트롤를 삭제하고, ListBox 컨트롤로 변경한 후, 데이터 보여주기
Code
Page.xaml // DataGrid 컨트롤 삭제하고, ListBox 컨트롤 로 대체함. <ListBox x:Name="lbResult" Grid.Row="1"></ListBox> Page.xaml.cs void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error == null) { //Using LINQ to XML to Parse NaverOpenAPI XML Items into Book Class XDocument xmlBooks = XDocument.Parse(e.Result); var books = from book in xmlBooks.Descendants("item") select new Book { BookName = (string)book.Element("title"), LinkUrl = new Uri((string)book.Element("link")), ImageUrl = new Uri((string)book.Element("image")), Author = (string)book.Element("author"), Price = (int)book.Element("price"), Publisher = (string)book.Element("publisher"), PubDate = (string)book.Element("pubdate"), ISBN = (string)book.Element("isbn"), Description = (string)book.Element("description") }; // XML Parse 한 데이터 바인딩하기 lbResult.ItemsSource = books; } } |
Result
Description
ð 검색 버튼 클릭 시, ListBox 에 해당 데이터 영역에“바인딩된 컬렉션명”이 나타나는데, ListBox 컨트롤 부분에 <ListBox x:Name="lbResult" DisplayMemberPath="BookName" Grid.Row="1"></ListBox> 어떤 데이터를보여줄지 매핑을 하지 않았기 때문입니다. 위와 같이 DisplayMemberPath를 지정해 주시면,아래와 같이 원하는 데이터를 화면에 보여줍니다.
- ListBox.ItemTemplate를 이용한 DataTemplate 구현하기
Code
Page.xaml <ListBox x:Name="lbResult" Grid.Row="1"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 이름 : </TextBlock> <TextBlock x:Name="txtBookName" Margin="5" Text="{Binding BookName}"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 소개 :</TextBlock> <TextBlock x:Name="txtBookDesc" Margin="5" Text="{Binding Description}"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 발행일 :</TextBlock> <TextBlock x:Name="txtBookPubDate" Margin="5" Text="{Binding PubDate}"></TextBlock> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> |
Result
Description
ð ListBox에 1개 이상의 정보를 보여줄 경우, ListBox 컨트롤의 ItemTemplate안에 DateTemplate를 정의하여 표현하고자하는 UI를 표현할 수 있습니다.
ð DataTemplate 안에는 한 개의 컨트롤만 사용 가능하나, 여러 개의 컨트롤을 사용할 경우, StackPanel를 감싸줘서 사용할 수 있습니다.
3. Tooltips (중요)
- Part3의 “Silverlight Network 이해하기” 에서 Silverlight Application은 보안을 위한 URL 접근이 제약되어 있고, 보안 정책 파일을 통해 특정 클라이언트의 접근을허용할 수 있다고 설명 드렸습니다. 우선 샘플 코드를 통해 자세한 설명을 이어가겠습니다.
- ListBox컨트롤의 ItemTempalte 에검색한 책 이미지를 넣어보겠습니다.
Code
Page.xaml <ListBox x:Name="lbResult" Grid.Row="1" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 이미지 :</TextBlock> <Image Source="{Binding ImageUrl}" Width="16" Height="10"></Image> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 이름 :</TextBlock> <TextBlock x:Name="txtBookName" Margin="5" Text="{Binding BookName}"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 소개 :</TextBlock> <TextBlock x:Name="txtBookDesc" Margin="5" Text="{Binding Description}"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Margin="5">책 발행일 :</TextBlock> <TextBlock x:Name="txtBookPubDate" Margin="5" Text="{Binding PubDate}"></TextBlock> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> |
Result
Description
ð 결과 화면처럼 에러 코드 : 4001 , 범주 : ImageError , 메시지 : AG_E_NETWORK_ERROR 가 발생하는 것을 볼 수 있습니다. 좀 더 자세히 알아보기 위해 HttpWatch, Fildder인 IE 개발 툴을 사용하여 요청한기록(아래 이미지)을 보면 요청한 도메인 최상위 루트에 clientaccesspolicy.xml 파일과 crossdomain.xml를먼저 요청하는 것을 볼 수 있습니다. 크로스 도메인 접근시 자동으로 요청하는 2개의 파일입니다.
ð Clientaccesspolicy.xml 파일은 Silverlight에서 사용하는 보안 정책 파일이고, Crossdomain.xml 파일은 기존에 어드비 플래시에서 사용하는 정책 파일로, 어떤 파일과 어떤 디렉토리를 접근 허용할지를 설정해 놓은 규약서라고 보시면 됩니다.
- 보안 정책 파일 작성하고 배포하기
ð 이 사이트의 모든 경로나 파일의 접근이 가능하도록 작성하였습니다.
Code
Clientaccesspolicy.xml <?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy> |
추가 설명 (예시) <resource path="/demo" include-subpaths="false"/> 로 지정시, 허용되는 접근 demo#intro /demo?bar=true#intro 허용되지 않는 접근 /demo /demo.txt /demo/sample /demo/sample.txt /demo/sample?bar=true /sample <resource path="/demo" include-subpaths="true"/> 로 지정시, 허용되는 접근 /demo/sample /demo/sample.txt /demo/sample?bar=true /demo#intro 허용되지 않는 접근 /sample |
Crossdomain.xml <?xml version="1.0"?> <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <allow-access-from domain="*"/> <allow-http-request-headers-from domain="* " headers="*" /> </cross-domain-policy> |
ð 위 코드와 같이 작성한 후, 사이트 최상위 루트에 배포하시면 됩니다.