Microsoft MVP성태의 닷넷 이야기
Phone: 10. Xamarin.Forms - 1. Forms 시작하기 [링크 복사], [링크+제목 복사],
조회: 24017
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
[Part1.zip]    

(시리즈 글이 3개 있습니다.)
개발 환경 구성: 183. Xamarin 2.0 - 윈도우 환경의 Visual Studio에서 C#으로 iOS/Android 응용 프로그램 개발
; https://www.sysnet.pe.kr/2/0/1415

Phone: 10. Xamarin.Forms - 1. Forms 시작하기
; https://www.sysnet.pe.kr/2/0/1699

Phone: 11. Xamarin.Forms - 2. XAML을 이용한 페이지 개발
; https://www.sysnet.pe.kr/2/0/1702




Xamarin.Forms - 1. Forms 시작하기

이번에 Xamarin이 버전 3을 발표하면서 물건을 내놨습니다. ^^ 바로 Xamarin.Forms 인데요. 기존의 Xamarin 앱이 C# 문법만을 사용했을 뿐 각각의 플랫폼(iOS, Android)에서 앱을 만들려면 고유의 User Interface 관련 API를 익혀야 했습니다.

하지만, Xamarin.Forms가 나오면서 이런 상황이 바뀝니다. 물론, 앱은 각각의 플랫폼 별로 프로젝트가 있어야 하지만 UI 요소만큼은 Xamarin.Forms를 이용해 공통화했습니다. 게다가 플랫폼도 기존의 iOS, Android와 함께 Windows Phone (8.0 이상)까지 지원을 넓혔습니다. 한마디로, 1타 3피의 성과를 낼 수 있는데 예전 같으면 이런 경우 "Web App"을 이용해야 했지만 Xamarin을 통해 빠른 속도의 앱을 보장하면서도 3가지 주요 모바일 플랫폼을 지원할 수 있게 된 것입니다.

Xamarin.Forms 소개를 어떻게 할까 고민하던 중에 외국 블로거가 이미 쓰고 있어서, 이를 적당히 참고해서 소개하겠습니다. ^^

Learning Xamarin - Part 1: Forms
; http://blog.falafel.com/Blogs/jesse-liberty/2014/06/11/learning-xamarin---part-1-forms




어차피 Xamarin을 구매할 정도의 국내 업체라면 Visual Studio도 충분히 구비하고 있을 것이라 생각됩니다. 따라서 이 글에서는 Xamarin Studio를 이용하기 보다는 Visual Studio를 이용해 실습을 진행하겠습니다. (사실, 어느 걸로 해도 상관없습니다. 단지, Visual Studio의 에디터가 더 훌륭하기 때문에 선택한 것일뿐.)

Xamarin 3을 설치한 다음 Visual Studio 2013에서 새 프로젝트를 만들면 다음과 같이 "Mobile Apps" 영역에서 Xamarin.Forms 관련 프로젝트를 선택할 수 있습니다. 이 중에서 앱을 만들 것이기 때문에 "Blank App (Xamarin.Forms Portable)"로 프로젝트를 시작하겠습니다.

xamarin_forms_part1_1.png

프로젝트를 생성하면 다음과 같이 총 4개의 프로젝트가 만들어집니다.

xamarin_forms_part1_2.png

아하~~~ 이제 알겠습니다. ^^ 각각의 개별 Mobile App 플랫폼 별로 프로젝트가 생성되고, 공통 Form 관련 프로젝트(위에서는 Part1 프로젝트)가 있습니다. 즉, UI 관련 프로젝트를 3개의 모바일 폴랫폼에서 공유할 수 있도록 하는 것입니다. (일단, 제 컴퓨터에서는 iOS를 빌드할 수 있는 맥이 없으므로 Part1.iOS 프로젝트는 제거하겠습니다.)

예제를 위해 다음과 같은 데이터 클래스를 (Portable) 프로젝트에 만듭니다.

public class Monkey
{
    public string Name {get;set;}
    public string Location { get; set; }
    public string Details { get; set; }
}

이것을 Xamarin.Form과 연결해 줄 방법으로 "Learning Xamarin - Part 1: Forms" 글에서는 MVVM을 사용하고 있습니다. 3개의 모바일 플랫폼 유형에서 UI Form만 공유할 것이기 때문에 MVVM 방식은 꽤나 멋진 접근법이 될 수 있습니다.

따라서 MonkeysViewModel.cs 파일을 추가하고 다음의 코드를 추가합니다.

using Part1;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Monkeys.ViewModels
{
    public class MonkeysViewModel
    {
        public ObservableCollection<Monkey> Monkeys { get; set; }

        public MonkeysViewModel()
        {
            Monkeys = new ObservableCollection<Monkey>();
            Monkeys.Add(new Monkey
            {
                Name = "Baboon",
                Location = "Africa & Asia",
                Details = "Baboons are African and Arabian Old World monkeys belonging to the genus Papio, part of the subfamily Cercopithecinae."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Capuchin Monkey",
                Location = "Central & South America",
                Details = "The capuchin monkeys are New World monkeys of the subfamily Cebinae. Prior to 2011, the subfamily contained only a single genus, Cebus."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Blue Monkey",
                Location = "Central and East Africa",
                Details = "The blue monkey or diademed monkey is a species of Old World monkey native to Central and East Africa, ranging from the upper Congo River basin east to the East African Rift and south to northern Angola and Zambia"
            });


            Monkeys.Add(new Monkey
            {
                Name = "Squirrel Monkey",
                Location = "Central & South America",
                Details = "The squirrel monkeys are the New World monkeys of the genus Saimiri. They are the only genus in the subfamily Saimirinae. The name of the genus Saimiri is of Tupi origin, and was also used as an English name by early researchers."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Golden Lion Tamarin",
                Location = "Brazil",
                Details = "The golden lion tamarin also known as the golden marmoset, is a small New World monkey of the family Callitrichidae."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Howler Monkey",
                Location = "South America",
                Details = "Howler monkeys are among the largest of the New World monkeys. Fifteen species are currently recognized. Previously classified in the family Cebidae, they are now placed in the family Atelidae."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Japanese Macaque",
                Location = "Japan",
                Details = "The Japanese macaque, is a terrestrial Old World monkey species native to Japan. They are also sometimes known as the snow monkey because they live in areas where snow covers the ground for months each"
            });

            Monkeys.Add(new Monkey
            {
                Name = "Mandrill",
                Location = "Southern Cameroon, Gabon, Equatorial Guinea, and Congo",
                Details = "The mandrill is a primate of the Old World monkey family, closely related to the baboons and even more closely to the drill. It is found in southern Cameroon, Gabon, Equatorial Guinea, and Congo."
            });

            Monkeys.Add(new Monkey
            {
                Name = "Proboscis Monkey",
                Location = "Borneo",
                Details = "The proboscis monkey or long-nosed monkey, known as the bekantan in Malay, is a reddish-brown arboreal Old World monkey that is endemic to the south-east Asian island of Borneo."
            });
        }
    }
}

데이터가 마련되었으니, 이제 3개의 프로젝트(여기서는 iOS제외 2개)에서 공통적으로 사용할 페이지를 만들어 보겠습니다. 역시 (Portable) 프로젝트에 MonkeyPage.cs 파일을 추가하고 코드를 만들어 줍니다.

using Monkeys.ViewModels;
using Xamarin.Forms;

namespace Part1
{
    public class MonkeyPage : ContentPage
    {
        public MonkeyPage()
        {
            Title = "Monkeys";

            var list = new ListView();

            var viewModel = new MonkeysViewModel();
            list.ItemsSource = viewModel.Monkeys;

            var cell = new DataTemplate(typeof(TextCell));

            cell.SetBinding(TextCell.TextProperty, "Name");
            cell.SetBinding(TextCell.DetailProperty, "Location");

            list.ItemTemplate = cell;

            Content = list;
        }
    }
}

위의 코드를 이해하려면 WPF를 알고 있어야 합니다. 왜냐하면 Xamarin.Forms는 이름과는 달리 윈도우 폼이 아닌 WPF 방식을 채택하고 있기 때문입니다. (여기서 WPF에 대한 설명을 하는 것은 어렵기 때문에 넘어가겠습니다. ^^)

자, 이제 이렇게 만들어진 앱 페이지를 각각의 플랫폼 프로젝트에서 사용해야겠지요. ^^

그 방법은 (Portable) 프로젝트의 App.cs에 정의된 GetMainPage가 해결해 줍니다. 즉, 3개의 앱 프로젝트는 (Portable) 프로젝트의 App.GetMainPage가 반환하는 페이지를 화면에 보여주는 것입니다. 따라서, 다음과 같이 App.cs 코드를 (기존 내용은 지우고) 구성하면 됩니다.

using Xamarin.Forms;

namespace Part1
{
    public class App
    {
        public static Page GetMainPage()
        {
            var monkeys = new MonkeyPage();
            return new NavigationPage(monkeys);

        }
    }
}

끝입니다. 여기까지 코드를 구성했으면 이제 "Part1.WinPhone (Windows Phone 8.0)" 프로젝트를 빌드하고 (에뮬레이터로) 실행하면 이렇게 보입니다.

xamarin_forms_part1_3.png

이어서 "Part1.Android" 프로젝트를 빌드하고 (에뮬레이터로) 실행하면 이렇게 보입니다.

xamarin_forms_part1_4.png

오... 그렇군요. 안타깝지만 아직 UI를 똑같이 보여주지는 않습니다. ^^ 따지고 보면, 윈폰에서 Detail 속성의 텍스트가 파란색으로 나오는 것이 오히려 이상합니다. 위의 코드에 보면 우리는 파란색이 나오라고 지정한 것이 없기 때문입니다. 아마도 Xamarin 측에서 TextCell.DetailProperty를 자동으로 파란색으로 바인딩하는 것 같은데, 그 처리를 안드로이드에서는 아직 구현을 못한 것 같습니다.




첫 페이지는 그렇게 했고, 그럼 다른 페이지로의 네비게이션은 어떻게 할 수 있을까요? 이를 위해 ListView 컨트롤의 항목을 눌렀을 때 상세 페이지로 넘어가는 것을 "Learning Xamarin - Part 1: Forms"글에 설명된 데로 구현해 보겠습니다.

우선, MonkeyPage 만들때처럼 ContentPage를 상속받는 DetailPage.cs를 (Portable) 프로젝트에 추가합니다.

using Xamarin.Forms;

namespace Part1
{
    public class DetailPage : ContentPage
    {
        public DetailPage(Monkey monkey)
        {
            this.Title = monkey.Name;

            var details = new Label
            {
                Text = monkey.Details
            };

            Content = new ScrollView
            {
                Padding = 20,
                Content = details
            };
        }
    }
}

그리곤 MonkeyPage.cs에 포함된 ListView 항목이 선택되는 것에 대한 이벤트 처리기를 만들고 DetailPage에 네비게이션하는 코드를 넣어줍니다.


using Monkeys.ViewModels;
using Xamarin.Forms;

namespace Part1
{
    public class MonkeyPage : ContentPage
    {
        public MonkeyPage()
        {
            // ... [생략] ...

            list.ItemTapped += (sender, args) =&gt;
            {
              var monkey = args.Item as Monkey;
              if (monkey == null)
                return;

              Navigation.PushAsync(new DetailsPage(monkey));
              list.SelectedItem = null;
            };

            Content = list;
        }
    }
}

보시는 바와 같이 Navigation 객체의 PushAsync를 이용해 다른 페이지로 네비게이션하고 있습니다. 역시 이번에도 실행해 보면 윈도우폰/안드로이드폰 모두 잘 동작합니다.

이 정도면, Xamarin.Forms에 대해서 대강 감이 오시겠죠? ^^

(첨부 파일은 위의 예제 코드를 구현한 Xamarin 프로젝트입니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 7/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2014-07-08 02시03분
멋지군요. Xamarin.Forms 관련 라이브러리들이 등장하는군요.

XForms/Xamarin-Forms-Labs
; https://github.com/XForms/Xamarin-Forms-Labs

--------------------------------------------------------

Microsoft Graveyard
; https://microsoftgraveyard.com/
정성태
2021-01-26 07시53분
[.NET Conf 2021 x Seoul] 닷넷으로 하는 크로스 플랫폼 앱 개발의 현재와 미래 (동영상 57분)
; https://www.youtube.com/watch?v=WdssztHlPDI
정성태

... 151  152  153  154  155  156  157  158  159  160  [161]  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1023정성태4/20/201130079.NET Framework: 210. Windbg 환경에서 확인해 본 .NET 메서드 JIT 컴파일 전과 후 [1]
1022정성태4/19/201125633디버깅 기술: 38. .NET Disassembly 창에서의 F11(Step-into) 키 동작파일 다운로드1
1021정성태4/18/201127957디버깅 기술: 37. .NET 4.0 응용 프로그램의 Main 함수에 BreakPoint 걸기
1020정성태4/18/201128600오류 유형: 117. Failed to find runtime DLL (mscorwks.dll), 0x80004005
1019정성태4/17/201129245디버깅 기술: 36. Visual Studio의 .NET Disassembly 창의 call 호출에 사용되는 주소의 의미는? [1]파일 다운로드1
1018정성태4/16/201132883오류 유형: 116. 윈도우 업데이트 오류 - 0x8020000E
1017정성태4/14/201127663개발 환경 구성: 115. MSBuild - x86/x64, .NET 2/4, debug/release 빌드에 대한 배치 처리파일 다운로드1
1016정성태4/13/201143698개발 환경 구성: 114. Windows Thin PC 설치 [2]
1015정성태4/9/201129066.NET Framework: 209. AutoReset, ManualReset, Monitor.Wait의 차이파일 다운로드1
1014정성태4/7/2011106483오류 유형: 115. ORA-12516: TNS:listener could not find available handler with matching protocol stack [2]
1013정성태4/7/201124284Team Foundation Server: 45. SharePoint 2010 + TFS 2010 환경에서 ProcessGuidance.html 파일 다운로드 문제
1012정성태4/6/201133023.NET Framework: 208. WCF - 접속된 클라이언트의 IP 주소 알아내는 방법 [1]
1011정성태3/31/201135418오류 유형: 114. 인증서 갱신 오류 - The request contains no certificate template information.
1010정성태3/30/201126182개발 환경 구성: 113. 응용 프로그램 디자인 스케치 도구 - SketchFlow [4]
1009정성태3/29/201138516개발 환경 구성: 112. Visual Studio 2010 - .NET Framework 소스 코드 디버깅 [4]
1008정성태3/27/201130893.NET Framework: 207. C# - Right operand가 음수인 Shift 연산 결과 [2]
1007정성태3/16/201131717개발 환경 구성: 111. Excel - XML 파일 연동 [5]파일 다운로드1
1006정성태3/15/201125505.NET Framework: 206. XML/XSD - 외래키처럼 참조 제한 거는 방법파일 다운로드1
1005정성태3/11/201135293개발 환경 구성: 110. 엑셀 매크로 함수 관련 오류 [2]
1004정성태3/3/201124497개발 환경 구성: 109. SharePoint Health Analyzer 디스크 부족 경고 제어
1003정성태3/3/201125514오류 유형: 113. SQL Server - DB Attach 시 Parameter name: nColIndex 오류 발생
1002정성태3/2/201123900Team Foundation Server: 44. TFS 설치 후, Team Portal의 Dashboard를 빠르게 확인하는 방법
1001정성태3/2/201127945Team Foundation Server: 43. TFS 2010 + SharePoint 2010 설치
1000정성태3/1/201132907오류 유형: 112. Remote FX RDP 연결 시 오류 유형 2가지 [5]
999정성태2/28/201146464개발 환경 구성: 108. RemoteFX - Windows 7 가상 머신에서 DirectX 9c 환경을 제공 [5]
998정성태2/27/201120168Team Foundation Server: 42. TFS Application-Tier만 재설치
... 151  152  153  154  155  156  157  158  159  160  [161]  162  163  164  165  ...