CAFE

Future Of DotNet

WPF, UWP 프로젝트를 Uno Platform으로 포팅하기

작성자카키104|작성시간20.12.22|조회수147 목록 댓글 0

2020년은 오프라인 비지니스 환경에서 언텍트 비지니스 환경으로 변화하는 변곡점이라고 할 수 있을 것 같습니다. 그에 따라 이제는 PC 뿐만 아니라 다양한 모바일 디바이스에서 실행되는 크로스플랫폼 개발 환경이 더욱더 발전을 할 것이라고 생각됩니다.

 

2018년 5월 최초로 공개된 Uno Platform은 크로스 플랫폼에서 실행되는 비지니스 응용 프로그램을 개발하는 가장  빠른 방법이라고 생각하며, 이 포스트에서 Microsoft Contoso UWP앱을 Uno Platform Prism으로 포팅할 때 참고할 사항이나 필요한 기술에 대해서 이야기를 하려고 합니다. Uno Platform에 대한 더 자세한 사항은 여기를 참고하시기 바랍니다.

 

Contoso UWP app

https://github.com/microsoft/Windows-appsample-customers-orders-database

UnoContoso app – Uno Platform

Uno.Samples/UI/UnoContoso at master · unoplatform/Uno.Samples (github.com)

 

포팅시 어려웠던 부분?

  1. Entity Framework Core 버전이 2.1에서 3.x 버전으로 변경되면서 발생한 문제를 해결하는데  시간이 오래 걸렸습니다. 변경 사항은 여기를 참고하시기 바랍니다.
  2. Sqlite를 Entity Framework Core를 이용해서 앱에서 직접 접근해서 사용하는 방식이 Wasm, iOS, macOS 등에서 원활하지 않아서, Web API를 통해서만 사용할 수 있도록 수정하는데 시간이 좀 걸렸습니다.
  3. Contoso UWP앱이 Event-driven 방식을 사용하고 있어서, 그 부분을 MVVM Pattern으로 변경하는 부분도 시간이 걸렸습니다.

프로젝트에 대한 간단한 설명

  • UnoContoso.Droid : 안드로이드 해더 프로젝트
  • UnoContoso.iOS : iOS 헤더 프로젝트
  • UnoContoso.macOS : macOS 헤더 프로젝트
  • UnoContoso.Uwp : Uwp 헤더 프로젝트
  • UnoContoso.Wasm : Wasm 헤더 프로젝트
  • UnoContoso.Models : 모델 프로젝트, .NET Standard 2.0
  • UnoContoso.Repository : 레파지토리 프로젝트, .NET Standard 2.0
  • UnoContoso.Service : 서비스 프로젝트, .NET Core 3.1
  • UnoContoso.Shared : 공유 프로젝트

Tips

  • NavigationView
    • AlwaysShowHeader=”False” :상단에 헤더를 표시하지 않습니다. 헤더를 표시하는 것 보다 표시 하지 않는 것이 아래의 이유로 인해서 개발이 용이 합니다.
      • iOS의 경우 헤더의 위치가 다른 플랫폼과 다르게 위로 올라가서 표시됩니다.
      • Windows, Wasm, macOS에서는 헤더 위치에 CommandBar를 표시하고, Android, iOS에서는 화면 하단에 표시하기 때문에, NavigationView.HeaderTemplate을 사용이 어렵습니다.
    • NavigationViewBehavior : NavigationView에 표시되는 메뉴를 동적으로 구현하고, 선택된 Menu를 ViewModel에 바인딩하기 위해서 Behavior를 만들었습니다. Behavior의 일반적인 사항은 여기를 참고하시기 바랍니다.
    • ContentControl : Prism에서 일반적으로 Region을 지정하는 컨트롤입니다. 이 컨트롤을 통해서 View가 네비게이션 됩니다. 더 자세한 사항은 Prism의 RegionNavigation을 참고하시기 바랍니다.
      • 이 컨트롤의 Padding은 각 화면의 기본 Margin입니다.
      • iOS의 경우 ios:Padding=”10,20,0,0” 을 사용해야 합니다.
  • x:Bind
    • Android와 iOS 앱의 성능 향상을 위해서 x:Bind를 주로 사용했습니다.
    • x:Bind를 사용하기 위해서 code behind에서ViewModel이라는 프로퍼티를 추가합니다. (Code2-1)
    • x:Bind의 기본 mode는 OneTime입니다. 그래서, 프로퍼티의 데이터가 변경되는 곳이라면 mode=OneWay를 반드시 추가해야 합니다.
    • 컨트롤의 이벤트와 뷰모델의 메소드를 x:Bind를 직접 연결하는 방법은 사용할 수 없습니다.
    • IValueConverter를 이용하는 경우 Android에서  x:Bind는 사용할 수 없기 때문에, Binding을 사용합니다. (Code2-2)
  • Prism
    • View와 ViewModel을 자동으로 연결해 줍니다. prismMvvm:ViewModelLocator.AutowireViewModel="True" 코드를 참고 합니다. 자세한 사항은 여기를 참고 합니다.(Code3-1)
    • RegionNavigation을 사용하기 위해서는 App.xaml.cs → void RegisterTypes() 메소드에 RegisterForNavigation을 이용해서 등록해야 합니다. (Code3-2)
    • DialogService를 사용하는 화면은 View와 ViewModel을 수동으로 연결 합니다. App.xaml.cs -} void RegisterTypes() 메소드에 있는 코드를 참고 합니다.  더 자세한 사항은 여기를 참고 합니다. (Code3-3)
    • DelegateCommand의 ObservesProperty를 이용하면, Command의 사용여부를 쉽게 변경할 수 있습니다. 더 자세한 사항은 여기를 참고 합니다. (Code3-4)
    • EventAggregator를 이용하면 뷰모델과 뷰모델 사이에 커뮤니케이션을 할 수 있습니다. 이는 Loosely Coupled 연결입니다. 더 자세한 사항은 여기를 참고 합니다. (Code3-5)
  • RelativePanel
    • 각 컨트롤을 관계에 의해 배치 합니다. 자세한 사항은 여기를 참고 하시기 바랍니다.
    • VisualState를 이용해서 상단에 위치한 CommandBar의 위치를 하단으로 변경할 때 CommandBar 컨트롤에 RelativePanel.LeftOf와 RelativePanel.RightOf에 입력되어있는 이름을 지워주어야 하단으로 이동이 가능합니다. 이 부분은 UWP에서의 동작과는 다르게 동작합니다.
  • CommandBar
    • 커맨드 버튼을 배치하는 컨트롤 입니다. 기본적인 사항은 여기를 참고하시기 바랍니다.
    • CommandBarBehavior는 크기가 변하면 DefaultLabelPosition을 Right에서 Bottom으로 이동 시키기 위해서 추가한 Behavior입니다.
    • DefaultLabelPosition 프로퍼티가 Uno에서 미구현 프로퍼티이기 때문에, 대부분의 플랫폼에서는 기본값 Bottm을 가지고 있습니다.
  • CollapsibleSearchBox
    • UserControl을 이용해서 만든 검색용 컨트롤입니다.
    • Uno에서 그래픽 아이콘은 SymbolIcon 컨트롤을 이용해야, 각 플랫폼에서도 정상적으로 아이콘이 출력됩니다.
  • ListView
    • 모바일 디바이스에서는 화면에 출력되는 항목의 갯수와 가로 스크롤바의 유무에 따라서 세로 스크롤 성능에 영향을 미치기 때문에 DataGrid보다는 ListView를 이용하는 것이 좋습니다. 더 자세한 사항은 여기를 참고 합니다.
    • macOS에서는 아직 DataGrid를 사용할 수 없기 때문에 ListView를 사용합니다. 하지만, macOS의 ListView도 컨트롤 내부에 ScrollView가 없기 때문에 세로 스크롤이 불가능한 것으로 보입니다. macOS 지원은 점점 추가될 것으로 생각합니다.
  • DataGrid
    • Data를 Grid 형태로 보여주며, 수정도 가능한 컨트롤이며, Windows Community Toolkit을 설치해야 사용할 수 있습니다. 더 자세한 사항은 여기를 참고 합니다.
    • DataGridBehavior는 Sort기능과 마우스 오른쪽 버튼을 지원하기 위해서 만들었습니다.
    • 컬럼에 프로퍼티를 바인딩 할때 x:Bind를 사용할 수 없습니다.
  • VisualState
    • 특정 상태일 때 UI 요소의 시각적 모양을 지정할 수 있는 기능입니다. 자세한 사항은 여기를 참고 합니다.
    • AdaptiveTrigger : 윈도우 속성을 기반으로 시각적 상태를 선언하는 트리거 입니다. 자세한 사항은 여기를 참고 합니다.  
    • VisualState를 이용해서 디자인 작업을 할 때, 기본 크기에 대한 디자인은 화면에 왼쪽 상단에서8” Tablet(1280x800)을 선택하고, 최소 크기에 대한 디자인은 6”Phone(1920x1080)을 선택해서 작업하면 약간 편하게 작업할 수 있습니다.
    • 최소 크기인 경우 PageTitle 컨트롤의 왼쪽에 30의 Margin을 추가해서 햄버거 버튼과 겹치는 현상을 방지 합니다.
    • MobileScreenTrigger는 윈도우 크기가 변경될 때 실행 중인 디바이스의 이름을 가지고 오고, Mobile이라는 이름을 포함하면 SetActive()를 이용해서 VisualState를 변경합니다. UIViewSettings.GetForCurrentView().UserInteractionMode는 Uno에서  미구현 상태라 주석 처리를 했습니다.
  • BackButton
    • 뒤로가기 버튼입니다. GoBackCommand 커맨드는 ViewModelBase에 선언되어 있습니다.
  • TextBox
    • 일반 텍스트를 표시하고 편집하는 데 사용하는 컨트롤 입니다. 자세한 사항은 여기를 참고 합니다.
    • Text 프로퍼티에 TwoWay바인딩을 할 때는 UpdateSourceTrigger=PropertyChanged를 이용하는 것이 좋습니다. 왜냐하면, 내용을 수정하면 바로 바인딩된 프로퍼티가 수정되기 때문입니다. 기본값은 LostFocus입니다. 
  • InvoiceTemplate (DataTemplate)
    • 데이터 개체의 시각적 구조를 만드는데 사용합니다. 자세한 사항은 여기를 참고 합니다.
    • HyperlinkButton이 1개가 존재하며 Command가 win과 not_win으로 나누어져 있습니다. 각 플랫폼별 xaml 코드를 적용하는 방법은 여기를 참고 합니다.
    • Windows에서는 win:Command="{Binding Source={StaticResource ViewModelElement}, Path=ViewModel.ViewInvoiceCommand}"를 사용해야 Command가 실행됩니다.
    • Windows가 아닌 경우에는 not_win:Command="{Binding ElementName=DataGrid,                     Path=DataContext.ViewInvoiceCommand}"를 사용해야 Command가 실행됩니다.
    • Windows에서 ElementName=DataGrid를 이용하는 방법이 않되는 이유는 모릅니다.
  • Etc
    • 만약 솔루션에 .Net Standard 프로젝트를 포함하고, 사용한다면, Wasm 프로젝트의 LinkerConfig.xml 파일에 해당 내용을 추가해야 합니다.

이상으로 작업을 하면서 알게된 몇가지 팁들을 정리했습니다. 앞으로도 좋은 정보가 있으면 꾸준히 올리도록 하겠습니다.

Facebook : https://www.facebook.com/kaki104

Twitter : https://twitter.com/kaki104

Youtube : http://youtube.com/FutureOfDotNet

 

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼