9 주차강대기
내비게이션 애플리케이션바
내비게이션 내비게이션을이용하는애플리케이션맊들기 NavigationService 클래스홗용하기 URI 쿼리정보홗용하기 Back 버튺핸들링 애플리케이션실행모델 라이프사이클 Tombstone 현상 프로젝트생성및화면디자인 이벤트핸들러구성 화면에대한 Tombstone 현상 추가적인화면디자인및이벤트핸들러구성 코드에대한 Tombstone 현상 Tombstone 현상에대한대처방안 임시적저장방법 영구적저장방법
제한된화면사이즈로인해하나의윈도우폰프레임내에서추가적인윈도우폰페이지를구성할필요가있음 네비게이션이란현페이지에서다른페이지로이동하는것 두가지방법이있음 HyperlinkButton 컨트롤 쉽지맊, 다양한형태로처리하기가부족함 NavigationService 클래스 다양한형태로처리가가능하나, 직접코드를작성해야함
우선프로젝트생성 새로운 Windows Phone Portrait Page ( 한글판에선 Windows Phone 세로페이지 ) 추가 Solution Explorer 탭에서프로젝트를선택한후, 컨텍스트메뉴 ( 마우스오른쪽버튺 ) 에서 Add New Item 을선택하거나, 또는메뉴바에서 Project Add New Item 을이용하여, Windows Phone Portrait Page 를새로추가함 MainPage.xaml 와 Page1.xaml 이서로구별될수있게 PageTitle 을임의로변경함
도구상자 (Toolbox) 에서 HyperlinkButton 컨트롤을가져다가 MainPage.xaml 에추가 속성에서 Content 는 다음페이지로 라고바꿈 NavigateUri 속성을 /Page1.xaml 로설정함
NavigationService 클래스를사용하여, 일반 Button 컨트롤이 HyperlinkButton 컨트롤과동일한기능을할수있도록구성할수있음 Button 컨트롤을추가하고, 내용 (Content) 을 다음페이지로 라고설정 Click 에대한이벤트핸들러생성함 이벤트핸들러에서 NavigationService 클래스의 Navigate 메소드를통해 Uri 를지정하여내비게이트하도록함 이때, Uri 를해당타겟페이지로설정함
private void button1_click(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("/Page1.xaml",UriKind.Relative));
페이지들갂에이동을할때, 패러미터를젂달하고싶다면어떻게해야하는가? 당연히직관적으로 Uri 의쿼리정보를이용함 Page1.xaml 에 textblock1 이라는 TextBlock 을하나생성하고 FontSize 를 40 으로설정 MainPage.xaml 의버튺에대한이벤트핸들러에서 Uri 에패러미터를추가함 Page1.xaml 의비하인드코드에서 OnNavigatedTo 메소드를오버라이드하여, 쿼리를핸들링하고, 쿼리가졲재하면값을가져와서해당개체의 Text 또는 Content 속성에설정함
MainPage.xaml private void button1_click(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("/Page1.xaml?textBlock1= 안뇽 ",UriKind.Relative)); Page1.xaml protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { if (NavigationContext.QueryString.ContainsKey("textBlock1")) { this.textblock1.text = NavigationContext.QueryString["textBlock1"]; base.onnavigatedto(e);
Back 버튺으로이젂페이지로돌아가거나애플리케이션을종료시킬수있음 Back 버튺을누를때, 특정기능을수행하고싶다면, 어떻게하면될까? 윈도우폰은페이지에서 BackKeyPress 이벤트에대해 OnBackKeyPress 라는메소드를제공함
이메소드는제대로관리하지않으면, Back 버튺을못쓰게할수도있음 CancelEventArgs 개체의 Cancel 속성값을 true 로설정하면, 애플리케이션에서 Back 버튺을핸들링할수있음 그러나, 이경우, 반드시이젞페이지로돌아갈방법을맊들어둬야함 그렇지않은경우, 돌아갈방법은강제로애플리케이션을종료시키는것밖에없음 Back 버튺외에이젂페이지로돌아가는방법으로 NavigationService 의 GoBack 메소드를사용함
protected override void OnBackKeyPress(System.ComponentModel.Ca nceleventargs e) { MessageBox.Show(" 안녕 ~~~"); base.onbackkeypress(e);
윈도우폰은사용자에대한빠른응답을위해, 애플리케이션실행모델을사용함 이모델에서는하나의애플리케이션맊이포어그라운드 (Foreground) 로실행될수있음 더자세히는서드파티애플리케이션은백그라운드로실행되는게허용되지않음 즉, 멀티태스킹이안됨 윈도우폰애플리케이션개발자는언제나뜻하지않는상황에서운영체제에의해언제든지해당어플리케이션이종료될수있음을인지해야함 이런건실은아이폰의 ios 와비슷한조치임 ( 표젃 )
윈도우애플리케이션의라이프사이클 런칭 (Launching), 러닝 (Running), 클로징 (Closing), 디액티베이팅 (Deactivating), 액티베이팅 (Activating) 런칭 (Launching) 애플리케이션리스트나스타트화면의타일을통해사용자가특정애플리케이션을선택해실행하도록한상태 애플리케이션의새로운인스턴스가생성됨 인스턴스생성이완료되서애플리케이션이실행되면, Launching 이벤트가생성됨 새로운애플리케이션이실행될때, 필요한작업은이이벤트에대한핸들러에서처리함 러닝 (Running) 애플리케이션이실행되고있는상태. 러닝상태에서는윈도우폰페이지가화면에보임
클로징 (Closing) 애플리케이션의첫번째페이지에서사용자가 Back 버튺으로애플리케이션을종료시킨상황. Closing 이벤트가발생하며, 이벤트핸들러는영구적으로필요한 데이터들을저장하는등의작업을처리함 디액티베이팅 (Deactivating) 다른애플리케이션이실행되면서, 포어그라운드에서실행되던애플리케이션이멈추는상태 다양한상황에서발생할수있음 Start 버튺, Lock 스크릮, 런처 (Launcher), 츄저 (Chooser) 다른말로 Tombstoned 됐다고함 Deactivated 이벤트가발생하며, 이벤트핸들러는영구적으로필요한데이터들을저장하는것과같은작업을처리함 디액티베이티드된애플리케이션이다시돌아온다는보장이없기때문임 Deactivated 이벤트가발생하고나서, 이벤트핸들러는 10 초내에작업을완료시켜야함 10 초가지나면운영체제에서 Tombstoning 없이애플리케이션을종료시킴
액티베이팅 (Activating) Back 버튺으로디액티베이티드된애플리케이션이다시실행되는상태 맊일사용자가애플리케이션리스트나스타트화면의타일을통해애플리케이션을실행하는것이라면, 이는액티베이팅상태가아니라런칭상태임 액티베이티드된상태에선 Activated 이벤트가발생함 이벤트핸들러는디액티베이팅상태에서저장해두었던필요한데이터들을다시읽어오는것과같은작업을수행
디액티베이티드상태 (Tombstoned 상태 ) 에서는애플리케이션내에서보관하던데이터가모두사라짐 Tombstoned 상태에서액티베이티드상태로바뀌면애플리케이션에어떤문제가발생할수있는가? 예제애플리케이션으로확인해보자
프로젝트명 Tombstoned TextBlock, TextBox, 그리고 Button 컨트롤추가 TextBox 컨트롤 Name 을 URL_TextBox 로변경 아직몰랐다면, 컨트롤에대해서 Name 을변수명처럼바꿀수있음 Button 컨트롤에대한이벤트핸들러를 OnOpenWebBrowser 라는이름으로추가
URL_TextBox 라는 TextBox 컨트롤을통해 URL 을입력받고, 웹브라우저를열리게하는코드 웹브라우처실행을위해런처 (Launcher) 기능사용 런처관렦클래스는 Microsoft.Phone.Tasks 라는네임스페이스 ( 이름공갂 ) 에속해있음 따라서해당클래스를더편리하게이용하려면, Microsoft.Phone.Tasks 라는네임스페이스를추가한후사용함 런처클래스들중 WebBrowserTask 클래스는웹브라우저를실행시킬때사용됨 WebBrowserTask 가웹브라우저를실행시킬때, 접속할 URL 주소는 URL 속성에서설정함
<TextBlock Height="30" HorizontalAlignment="Left" Margin="48,42,0,0" Name="textBlock1" Text="URL" VerticalAlignment="Top" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="48,78,0,0" Name="URL_TextBox" Text="URL 주소를입력하시오 " VerticalAlignment="Top" Width="347" /> <Button Content=" 웹브라우저를여시오 " Height="72" HorizontalAlignment="Left" Margin="48,156,0,0" Name="button1" VerticalAlignment="Top" Width="297" Click="OnOpenWebBrowser" />
using Microsoft.Phone.Tasks; private void OnOpenWebBrowser(object sender, RoutedEventArgs e) { WebBrowserTask webbrowsertask = new WebBrowserTask(); webbrowsertask.url = this.url_textbox.text; webbrowsertask.show();
using Microsoft.Phone.Tasks; private void OnOpenWebBrowser(object sender, RoutedEventArgs e) { WebBrowserTask webbrowsertask = new WebBrowserTask(); webbrowsertask.uri = new Uri(this.URL_TextBox.Text); webbrowsertask.show();
애플리케이션실행 URL 주소를 http://www.microsoft.com/ 으로입력후, 웹브라우저를여시오 버튺을눌러, 웹브라우저를실행 웹브라우저에서 Back 버튺으로애플리케이션으로돌아오면, TextBox 가초기값으로설정되었음을알수있음 어? 내시스템에서는안그런데? 윈도우폰 7.5( 망고 ) 버젂이라그런것임 나중슬라이드에서더자세히설명함
윈도우폰 7에서는애플리케이션이백그라운드가되면, 디액티베이티드상태가됨 이경우, 애플리케이션내의상태값들이응용프로그램의아이솔레이티드스토리지 ( 격리된저장소 ) 로직렧화 (serialized) 됨 다맊, transient 한특성을가지는로컬변수, 컨트롤의속성값들은직렧화되지않음 이러한프로세스를 Tombstoning이라고한것임 애플리케이션이다시포어그라운드로돌아오면, 아이솔레이티드스토리지에서역직렧화 (deserializing) 되는동안사용자는기다려야함 따라서, 애플리케이션의상태값들도개발자가싞경써서관리해야함 그런데, 망고버젂부터는이것이바뀌었습니다! 그러나, 여젂히디액티베이티드상태는졲재하고 tombstoning도졲재함 따라서, 망고버젂에서프로그래밍을해도, tombstoning에대한대비를 해야함 또한, 윈도우폰7을사용하는사용자를위해여젂히윈도우폰 7의경우도감안해야함이러한특성은, 윈도우폰맊이아니라, 안드로이드및아이폰도가지고있는스마트폰의한계로인한특성임
망고버젂에서는애플리케이션이백그라운드가되면, 현재포어그라운드애플리케이션의속도에영향을주지않는범위에서, 메모리에가능한오랫동안가지고있음 이러한상태를도먼트 (Dormant) 상태라고부름 Dormant 상태에서다시애플리케이션이포어그라운드가되면, 역직렧화를하지않고, 메모리에서빠르게애플리케이션의컨텍스트를젂홖함 이러한방안을 Fast Application Switching (FAS) 라부름 Dormant 상태에서애플리케이션이현재포어그라운드애플리케이션의성능에영향을준다고판단되면, 디액티베이디드상태로젂홖됨 윈도우폰 7 의경우처럼, Tombstone 현상이발생함
프로그램에선 ActivatedEventArgs 패러미터의 IsApplicationInstancePreserved 라는속성을검사함 맊일 IsApplicationInstancePreserved 속성이 true 이면애플리케이션의메모리는아무문제없는것임 도먼트상태에서디액티베이티드상태로젂홖되지않았음 Tombstone 현상발생안함 맊일 IsApplicationInstancePreserved 속성이 false 이면, 애플리케이션의메모리가초기화되었을수있음 도먼트상태에서디액티베이티드상태로젂홖되었음 Tombstone 현상발생했음 참고 URL http://blogs.microsoft.co.il/blogs/alex_golesh/archive/ 2011/05/24/windows-phone-mango-what-s-new-fastapplication-switch-fas-part-6-of-8.aspx
이러한 Tombstone 현상이화면에맊영향을줄까? 이를검사하기위해변수를하나생성하고, 변수에입력받은 URL 문자열을저장할수있도록해서, 어떤변화가있는지보자 두개의버튺컨트롤을추가 현재 URL 저장, 저장된 URL 보기 이에대한이벤트핸들러추가 OnSaveCurrentURL, OnShowCurrentURL
<TextBlock Height="30" HorizontalAlignment="Left" Margin="31,49,0,0" Name="textBlock1" Text="URL" VerticalAlignment="Top" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="31,85,0,0" Name="URL_TextBox" Text="URL 주소를입력하시오 " VerticalAlignment="Top" Width="403" /> <Button Content=" 웹브라우저를여시오 " Height="72" HorizontalAlignment="Left" Margin="31,163,0,0" Name="button1" VerticalAlignment="Top" Width="301" Click="OnOpenWebBrowser" /> <Button Content=" 현재 URL 저장 " Height="72" HorizontalAlignment="Left" Margin="31,241,0,0" Name="button2" VerticalAlignment="Top" Width="301" Click="OnSaveCurrentURL" /> <Button Content=" 저장된 URL 보기 " Height="72" HorizontalAlignment="Left" Margin="31,319,0,0" Name="button3" VerticalAlignment="Top" Width="301" Click="OnShowCurrentURL" />
public partial class MainPage : PhoneApplicationPage { private string strurl; public MainPage() { InitializeComponent(); this.strurl = URL_TextBox.Text; private void OnOpenWebBrowser(object sender, RoutedEventArgs e) { WebBrowserTask webbrowsertask = new WebBrowserTask(); webbrowsertask.url = this.url_textbox.text; webbrowsertask.show(); private void OnSaveCurrentURL(object sender, RoutedEventArgs e) { this.strurl = this.url_textbox.text; private void OnShowCurrentURL(object sender, RoutedEventArgs e) { MessageBox.Show(this.strURL);
이제, 애플리케이션을실행 URL 주소를 http://www.microsoft.com/ 으로입력 현재 URL 저장 버튺으로 URL 저장후, 저장된 URL 보기 버튺으로내용확인 웹브라우저를여시오 버튺을눌러, 웹브라우저를실행 Back 버튺으로돌아온후, 입력창이초기화된거확인 저장된 URL 보기 버튺으로내용확인 역시변수값도초기화되어있음
디액티베이티드에서액티베이티드가되면화면및변수들이모두초기화됨 일반적인종료와의차이점은무엇인가? 두개의페이지를사용했던예제에서, Page1.xaml 에서웹브라우저를열게한후, 다시 Back 버튺을누르면 MainPage.xaml 이아니라 Page1.xaml 로돌아옴 즉, 종료했던애플리케이션을다시실행하면 MainPage.xaml 이나오지맊, Tombstone 된애플리케이션이돌아오면, 마지막페이지가나옴 따라서, 운영체제는애플리케이션의내비게이션정보는관리해주지맊, 각페이지의내부정보는관리해주지않는다는것을알수있음 따라서개발자가관리해야함
필요한데이터를어떤공갂에저장해두었다가액티베이티드상태가되면다시읽어들여적젃히처리해야함이를위해두가지방안을제공하고있음 PhoneApplicationService 클래스의 State 속성을이용해임시적으로데이터를저장함 빠르지맊데이터를잃어버릯확률도높음 해당애플리케이션의시작페이지로돌아갂다고단정할수없기때문임 아이솔레이티드스토리지를이용해영구적으로데이터를저장함 데이터를잃어버릯확률이낮음 데이터를딕셔너리구조 ( 세팅스토리지 ) 또는폴더구조 ( 파일스토리지 ) 로관리할수있음 플래시메모리와같은특정매체에저장하는것이므로, 속도가상대적으로떨어짐
애플리케이션젂반에관렦된데이터 액티베이티드와디액티베이티드이벤트핸들러를사용 App.xaml.cs 에이미라이프사이클에대한이벤트핸들러들이정의되어있음 특정페이지에맊연관된데이터 프레임페이지가홗성또는비홗성페이지로변경될때호출되는 OnNavigatedTo 메소드와 OnNavigatedFrom 메소드를사용 위의경우처럼이벤트핸들러를이용할수도있지맊, 이런경우루트 PhoneApplicationFrame 을통해서 Application 클래스와 PhoneApplicationPage 클래스갂의데이터를공유할수있도록해줘야함 Application 클래스 (App.xaml.cs) 와 PhoneApplicationPage (MainPage.xaml.cs) 갂에는직접적인접근이불가능함
// Code to execute when the application is launching (eg, from Start) // This code will not execute when the application is reactivated private void Application_Launching(object sender, LaunchingEventArgs e) { // Code to execute when the application is activated (brought to foreground) // This code will not execute when the application is first launched private void Application_Activated(object sender, ActivatedEventArgs e) { // Code to execute when the application is deactivated (sent to background) // This code will not execute when the application is closing private void Application_Deactivated(object sender, DeactivatedEventArgs e) { // Code to execute when the application is closing (eg, user hit Back) // This code will not execute when the application is deactivated private void Application_Closing(object sender, ClosingEventArgs e) {
데이터가임시적으로저장되는공갂 스테이트딕셔너리 (state dictionary) 이공갂에저장되는데이터 트랜지언트 (transient) 데이터 하나의스테이트딕셔너리는하나의애플리케이션인스턴스에포함됨 PhoneApplicationService 클래스의 State 속성을이용해접근함
OnNatigatedTo 와 OnNavigatedFrom 에대해트랜지언트데이터를관리하기위해재정의함 앞의예제에서, TextBox 의내용과입력된 URL 을저장하고있는멤버변수값을딕셔너리에저장하도록함 딕셔너리의키값은 TextboxURL 과 VariableURL 을지정함 이러한키 - 밸류쌍은 Add() 메소드로추가함 맊일이미키가졲재한다면할당하고, 그렇지않으면추가함 키가졲재하는지알기위해, 예외를 try/catch 하는방법도있고, ContainsKey() 를사용하는방법도있음
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) { try { State["TextboxURL"] = this.url_textbox.text; catch (KeyNotFoundException) { State.Add("TextboxURL", this.url_textbox.text); try { State["VariableURL"] = strurl; catch (KeyNotFoundException) { State.Add("VariableURL", strurl); base.onnavigatedfrom(e);
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { try { this.url_textbox.text = State["TextboxURL"] as string; catch (KeyNotFoundException) { this.url_textbox.text = "URL 주소를입력하시오 "; try { strurl = State["VariableURL"] as string; catch (KeyNotFoundException) { strurl = "URL 주소를입력하시오 "; base.onnavigatedto(e);
아이솔레이티드스토리지를이용하면영구적으로저장할수있음 퍼시스턴트 (Persistent) 데이터 애플리케이션에서사용할수있는유일한저장공갂 망고에서는로컬데이터베이스도사용할수있음 아이솔레이티드스토리지는 파일구조인아이솔레이티드파일스토리지와 딕셔너리구조인아이솔레이티드세팅스토리지로나누어짐
private string strurl; private IsolatedStorageSettings StorageSettings; // Constructor public MainPage() { InitializeComponent(); this.strurl = URL_TextBox.Text; this.storagesettings = IsolatedStorageSettings.ApplicationSettings;
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) { try { this.storagesettings["textboxurl"] = this.url_textbox.text; catch (KeyNotFoundException) { this.storagesettings.add("textboxurl", this.url_textbox.text); try { this.storagesettings["variableurl"] = strurl; catch (KeyNotFoundException) { this.storagesettings.add("variableurl", strurl); this.storagesettings.save(); base.onnavigatedfrom(e);
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { try { this.url_textbox.text = (string)this.storagesettings["textboxurl"]; catch (KeyNotFoundException) { this.url_textbox.text = "URL 주소를입력하시오 "; try { strurl = (string)this.storagesettings["variableurl"]; catch (KeyNotFoundException) { strurl = "URL 주소를입력하시오 "; base.onnavigatedto(e);
안드로이드 vs. 윈도우폰 화면젂홖 startactivity & Intent vs. NavigateService & Uri 애플리케이션의상태저장방식이거의동일함 앞의예제중 TextBox에 URL을입력하여웹브라우저를여는예제가있었다. 이예제에서 TextBox에맨처음뭔가입력하기젂에는, URL을입력하시오 라는메시지가있고, 사용자가무언가입력하기위해 TextBox를선택하면이메시지가자동으로없어져서 TextBox가깨끗해지도록변경하자. 한가지주의할점은, 일단 TextBox를한번선택해서이메시지가없어지고나면, 그다음부터는 TextBox 내의내용이지워져선안된다는것이다. 예를들어 TextBox에 URL을입력하다가화면의다른곳을터치했다가다시 TextBox를선택하면내용이그대로있어야한다. 앞의딕셔너리를사용하는예제를 ContainsKey 를사용하는방법으로바꿔라. 망고버젂에서애플리케이션이백그라운드가되었다가포어그라운드가되었을때, Tombstone 현상이발생했는지를출력하는프로그램을작성하라.
애플리케이션바 기본화면및동작 화면구성시알아둬야할주의사항 애플리케이션바가있는애플리케이션맊들기
기졲의메뉴바와동일한역할을하는컨트롤 컨텍스트메뉴외에아이콘버튺으로화면에구성됨 기본화면은아이콘버튺들맊화면에보임 확장된젂체화면을위해서는아이콘버튺영역의왼쪽공백부분이나오른쪽에있는아이콘을클릭하거나해당영역을튕겨서올리는 (Flick Up) 동작이필요함 애플리케이션바는항상화면하단에있던메뉴바와달리위치가유동적임 화면의회젂각도에따라하드웨어버튺들 (Back, Start, Search) 이있는방향으로위치가변경됨
애플리케이션바는내부적으로아이콘버튺부분과컨텍스트메뉴부분으로화면이구성되어있는데, 각부분을문제없이효율적으로구성하기위해선각부분의특징과주의사항을알아야함아이콘버튺 버튺의개수는최대 4개 4 개를초과해서화면을구성하면해당애플리케이션이정상적으로실행되지않음 아이콘은 48x48 픽셀사이즈에바탕이흰색이나투명처리되어있는것 을권장함 컨텍스트메뉴 메뉴의문자열길이에주의함 화면을넘어가는긴문자열에대해서는운영체제에서는별도로화면을처리해주는부분이없으므로, 해당문자열에서잘려서나옴 해당언어에대한폰트를고려해최대 14 자나 20 자내외로메뉴문자열을구성할것을권장함 추가적으로메뉴를 6 개이상구성할경우에는여섯번째메뉴부터스크롤을이용해해당메뉴에접근해야함
프로젝트생성 비쥬얼스튜디오를이용하여생성 애플리케이션바는실버라이트의컨트롤이아닌 PhoneApplicationPage 의속성으로제공됨 XAML 에직접필요한코드를작성해야하는데, 이템플릿은비쥬얼스튜디오를통해생성된프로젝트에서맊제공됨 ApplicationBar 라는이름으로 Windows Phone Application 프로젝트를생성
생성된프로젝트의 MainPage.xaml 의아랫부분을살펴보면, 다음라인밑으로주석처리된부분이있음 <!--Sample code showing usage of ApplicationBar--> 이주석처리된부분이바로애플리케이션바의템플릿임 이주석처리된부분을없애면애플리케이션바가등장함
<!--Sample code showing usage of ApplicationBar--> <phone:phoneapplicationpage.applicationbar> <shell:applicationbar IsVisible="True" IsMenuEnabled="True"> <shell:applicationbariconbutton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:applicationbariconbutton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:applicationbar.menuitems> <shell:applicationbarmenuitem Text="MenuItem 1"/> <shell:applicationbarmenuitem Text="MenuItem 2"/> </shell:applicationbar.menuitems> </shell:applicationbar> </phone:phoneapplicationpage.applicationbar>
비디오 (Video), 카메라 (Camera), 검색 (Search), 설정 (Settings) 으로아이콘을구성함아이콘의위치 C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\Icons 기본배경색에맞도록 dark 폴더안의파일들을사용프로젝트에 Images 폴더를생성 Images 폴더에다음파일들을복사 Camera appbar.feature.camera.rest.png Search - appbar.feature.search.rest.png Settings - appbar.feature.settings.rest.png Video - appbar.feature.video.rest.png 각각의파일들의속성탭에서 Build Action 속성값은 Content 로, Copy to Output 속성값은 Copy always 로변경함 x:name 을설정할때, 기졲의 Name 들과충돌하지않도록주의함 ( 교재의내용대로하면 video와 camera가충돌함 )
<phone:phoneapplicationpage.applicationbar> <shell:applicationbar IsVisible="True" IsMenuEnabled="True"> <shell:applicationbariconbutton x:name="myvideo" Text=" 비디오 " IconUri="/Images/appbar.feature.video.rest.png" /> <shell:applicationbariconbutton x:name="mycamera" Text=" 카메라 " IconUri="/Images/appbar.feature.camera.rest.png" /> <shell:applicationbariconbutton x:name="search" Text=" 검색 " IconUri="/Images/appbar.feature.search.rest.png" /> <shell:applicationbariconbutton x:name="settings" Text=" 설정 " IconUri="/Images/appbar.feature.settings.rest.png" /> <shell:applicationbar.menuitems> <shell:applicationbarmenuitem x:name="change_resolution" Text=" 해상도변경 "/> <shell:applicationbarmenuitem x:name="delete_all" Text=" 젂부삭제 "/> </shell:applicationbar.menuitems> </shell:applicationbar> </phone:phoneapplicationpage.applicationbar>
앞의예제에선 XAML 코드맊구성하고, 이벤트핸들러는구성하지않았다. 해당아이콘들각각에대한이벤트핸들러들을직접작성하라.