강남 DataBinding 스타일 Windows 8 앱개발자라면 꼭 알아야할 개발자가 알아야할 Binding
Non-DataBinding vs. DataBinding <Grid> <TextBlock x:Name=“TitleText”/> <TextBlock x:Name=“SubTitleText”/> </Grid> TitleText.Text = item.Title; SubTitleText.Text = item.SubTitle; <Grid> <TextBlock Text=“{Binding Title}”/> <TextBlock Text=“{Binding SubTitle}”/> </Grid> this.DataContext = item;
버튼 누가 지웠어!
Non-DataBinding vs. DataBinding <Grid> <HyperlinkButton /> </Grid> TitleText.Text = item.Title; SubTitleText.Text = item.SubTitle; 컴파일 에러 발생!!! <Grid> <HyperlinkButton Content=“{Binding Title}”/> </Grid> this.DataContext = item; 컴파일 에러 없음 UI와 코드의 분리 개발자와 디자이너 업무영역의 분리 PEACE!
이번 앨범 타이틀 곡이 뭐야?
문맥
강남스타일! 문맥 너랑 나!
문맥 = Context
DataContext
FrameworkElement.DataContext 거의 모든 UI는 FrameworkElement
가정 class Chart class Album class Artist + Album FirstAlbum + List<Album> Albums class Album + string CoverArt + string Name + Artist Artist class Artist + string ProfilerImage + string Name
자식에게 상속하는 DataContext Visual Tree <Grid x:Name=“LayoutRoot” DataContext=“{Binding TopAlbum}”> <Image Source=“{Binding CoverArt}”/> <TextBlock Text=“{Binding Title}”/> <StackPanel DataContext=“{Binding Artist}”> <Image Source=“{Binding ProfileImage}”/> <TextBlock Text=“{Binding Name}”/> </StackPanel> </Grid> Grid(LayoutRoot) Image TextBlock Grid Image TextBlock
자식에게 상속하는 DataContext Visual Tree <Grid x:Name=“LayoutRoot” DataContext=“{Binding TopAlbum}”> <Image Source=“{Binding CoverArt}”/> <TextBlock Text=“{Binding Title}”/> <StackPanel> <Image Source=“{Binding Artist.ProfileImage}”/> <TextBlock Text=“{Binding Artist.Name}”/> </StackPanel> </Grid> Grid(LayoutRoot) Image TextBlock Grid Image TextBlock
DataContext 주입법 var chart = GetKPopChart(); this.DataContext = chart; <Page> <Page.Resources> <models:KPopChart x:Key=“Chart” /> </Page.Resources> <Grid DataContext=“{StaticResource Chart}”> ….. </Grid> </Page> In C# <Page> <Page.DataContext> <models:KPopChart x:Key=“Chart” /> </Page.DataContext> <Grid > ….. </Grid> </Page> In XAML
Binding
문법 Binding Path (생략가능) Source Converter ConverterParameter Text="{Binding Title}" Path (생략가능) Text=“{Binding Path=Title}” Source Text=“{Binding Name, Source={StaticResource MyViewModel}}” Converter Text=“{Binding PublishDate, Converter={StaticResource FamiliarDateString}}” ConverterParameter Text=“{Binding Price, Converter={StaticResource CurrencyConverter}, ConverterParameter=\{0:C2\}}”
{Binding } DataContext 자기 자신! <TextBlock Text=“{Binding }” />
ItemsControl
ItemsControl 가족 ListView GridView FlipView ListBox ComboBox Control .ItemsSource 프로퍼티가 여기 정의 Selector ListViewBase FlipView ListBox ComboBox ListView GridView
ItemsControl에서 DataContext 분배 var artists = new List<Artist>() { new Artist() { Name = “싸이”, CoverArt=“…”}, new Artist() { Name = “아이유”, CoverArt=“…”}, } this.Artists = artist; …. <ListView ItemsSource=“{Binding Artists}” /> CS에서 싸이 아이유 싸이 아이유 XAML에서
ItemTemplate과 DataContext new Artist() { Name = “싸이”, CoverArt=“…”, } ItemsSource의 인스턴스 하나가 ListViewItem 하나의 DataContext가 된다. 싸이 <ListView.ItemTemplate> <DataTemplate> <Grid> <StackPanel> <Image Source=“{Binding CoverArt}” /> <TextBlock Text=“{Binding Name}” /> </StackPanel> </Grid> </DataTemplate> </ListView.ItemTemplate>
In the hood protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { var contentControl = element as ContentControl; contentControl.ContentTemplate = this.ItemTemplate; contentControl.DataContext = item; } ItemsControl의 virtual PrepareContainerForItemOverride(…) 에서
INotifyPropertyChanged INotifyCollectionChanged
약속 컨트롤은 INotifyPropertyChanged.PropertyChanged를 구독합니다. 컨트롤은 INotifyCollectionChanged.CollectionChanged를 구독합니다. public abstract class BindableBase : INotifyPropertyChanged public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged Common/BindableBase.cs 에서 System.Collections.ObjectModel
이미 구현되어 있는 것 DataModel/SampleDataSource.cs에서 public abstract class SampleDataCommon : App4.Common.BindableBase private string _title = string.Empty; public string Title { get { return this._title; } set { this.SetProperty(ref this._title, value); } } protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; 프로퍼티 예 : Title In the Hood
List<Artist> vs. ObservableCollection<Artist> this.Artist.Add(new Artist()); this.Artist.Add(new Artist()); 싸이 싸이 아이유 아이유 싸이 싸이 아이유
Converter
어떤 필요, 어떤 니즈? public List<string> Artists { get; set; } … Artists = new List<string>() { “싸이”, “아이유”, }; 너랑 나랑 강남스타일 싸이, 아이유
샘플 ArtistConverter namespace MyApp { public class ArtistConverter : IValueConverter public object Convert(object value, Type targetType, object parameter, string language) // null 체크, value가 Ienumerable 타입이 아닐 때 예외처리 (생략) var list = value as IEnumerable; StringBuilder sb = new StringBuilder(); foreach (var item in list) if (sb.Length > 0) sb.Append(“, “); sb.Append((string)item); } return sb.ToString();
사용법 인스턴스 생성 (어딘가에) -> 바인딩 식에서 잘 사용 In MyView.xaml (or App.xaml) <Page> <Page.Resources> <conv:ArtistConverter x:Key=“ArtistConverter”/> </Page.Resources> <Grid x:Name=“LayoutRoot”> … <TextBlock Text=“{Binding Artists, Converter={StaticResource ArtistConverter}”/> </Grid> </Page> 너랑 나랑 강남스타일 싸이, 아이유
Blend 도와줘!
Sample Project Code Review
GridApp 샘플 프로젝트에서 protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { // TODO: Create an appropriate data model for your problem domain to replace the sample data var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter); this.DefaultViewModel["Groups"] = sampleDataGroups; } <common:LayoutAwarePage x:Name="pageRoot" x:Class="App4.GroupedItemsPage" DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}“ … <CollectionViewSource x:Name="groupedItemsViewSource" Source="{Binding Groups}" GroupedItemsPage.xaml.cs에서 GroupedItemsPage.xaml에서
FIN 즐거운 해커쏜(θ) 되세요!