WPF 에서 UWP API 사용하기

      WPF 에서 UWP API 사용하기에 댓글 2개

1. 개요

WPF기반에 Bluetooth Low Energy 관련하여 프로젝트를 하게 되었다.
응용프로그램에 Bluetooth 통신을 하려면 관련 Library의 집합체인 Bluetooth Stack 이라는 것을 활용해야 했다.
현재 사용할 수 있는 Bluetooth Stack은 아주 제한적이며 몇개 되지도 않았다. 그나마 범용적으로 사용할 수 있는게 Microsoft Bluetooth Stack.
하지만 이 녀석은 Windows 10 의 UWP 에서만 제공이 되었다.
그리하여 UWP가 아닌 C# 프로젝트에서 UWP를 사용할 수 있는 방법을 찾게 되어 정리한다.

2. 방법

크게 2가지 방법이 있다. 하나는 Project의 정보를 수정하여 UWP API를 사용하는 방법. 하나는 winmd 파일을 참조하는 방법. 일단 UWP 플랫폼이 아닌(물론 Xamarin도 아닌) 프로젝트를 하나 생성한다. 난 WPF로 하겠다.

2.1. *.csproj 파일 수정

프로젝트의 여러 정보가 담긴 파일인 *.csproj 파일편집을 위하여 별도의 메모장이나 텍스트에디트 프로그램으로 *.csproj 파일을 열어서 수정해도 되지만, Visual Studio에서 바로 수정도 가능하다.
솔루션탐색기에서 수정하고자 하는 프로젝트에 마우스 오른쪽 클릭하여 나타난 Context Menu 중에 ‘프로젝트 언로드(L)’를 클릭한다.

그러면 열려 있었던 프로젝트가 닫히면서 솔루션 탐색기에 ‘프로젝트명(사용할 수 없음)’ 으로 표시된다.
이 상태에서 다시 Context Menu를 열어 ‘편집 프로젝트명.csproj’ 메뉴를 선택한다.
프로젝트의 정보가 담긴 xml 파일을 편집할 수 있다.
이것 저것 많은 정보가 있지만 넘어가고, Project Element의 하위에 아래 정보를 추가한다.

저장 후, xml 편집기를 닫고, 솔루션 탐색기에서 프로젝트의 Context Menu를 열어 ‘프로젝트 다시 로드’ 메뉴를 선택한다.
일단, 정상적으로 빌드가 되는지 확인한다. xml 내용이 올바르지 않거나 수정이 잘못되었다면, 프로젝트가 로드되지않거나 빌드되지 않으니 주의하도록 한다.
빌드가 잘 되는지 확인하였다면, 솔루션 탐색기의 프로젝트의 참조 노드에서 Context Menu를 열어 ‘참조 추가’를 선택한다.
자주 보던 참조관리자가 열린다. 하지만, 처음보는 메뉴가 생겼다. ‘Universal Windows’!
‘핵심’ 노드를 선택하여 Windows를 체크하고, ‘확인’ 버튼을 눌러 참조를 추가한다.

아직 끝난게 아니다. UWP의 다양한 API들은 async / await 를 통하여 비동기 방식을 사용한다. UWP의 async / await와 None-UWP (WPF)의 async / await가 어떠한 차이가 있는지 알수는 없지만, UWP의 async / await 문법을 사용하려면 System.Runtime.WindowsRuntime.dll을 추가하여야 한다. 전체경로는
‘c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll’이다.

이로써 UWP API 사용을 위한 준비가 끝났다.
UWP API 가 정상동작 하는지 ‘Windows.Devices.Enumeration.DeviceWatcher’ 클래스를 사용하여 현재 시스템에 설치된 Device를 가져오는 코드를 샘플로 작성하였다.

빌드 후 실행하여 출력창을 확인하면 정상적으로 동작하는 것을 확인할 수 있다.

2.2. *.winmd 파일 참조 추가

보다 더 간단하게 UWP API를 사용하는 방법이 있다. 바로 Windows.winmd 파일을 프로젝트에 참조로 추가하는 방법이다.
전체 경로는
‘C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Windows.winmd’ 이다.
*.winmd 라는 확장자를 가진 파일을 참조추가 할 수 있다는 걸 이번에 처음 알았다.
위에서 했던 두번째 작업인 ‘System.Runtime.Windows.Runtime.dll’ 파일을 역시 참조에 추가한다.
끝! (응? 정말 간단하지 않은가?)
위에서 샘플로 작성한 코드를 복사하여 빌드, 실행 해보자. 정상 동작하는 것을 확인할 수 있다.

3.정리

두가지 방법중 첫번째 방법으로 프로젝트에 적용하여 사용중이었지만, dll 충돌이 일어난다던가 하는 자잘한 문제로 고생이 많았다. Windows.winmd 파일을 참조하여 사용하길 권한다.

전 회사에서 OCR 관련 라이브러리가 필요하였었는데, UWP API에 있는 OCR API를 사용했어도 좋았을 것 같다. Tesseract 라는 Open source를 사용하였으나, UWP의 OCR API 보다는 성능이 낮았다.

이제 UWP에서만 가능하던 모든 기능을 스토어 앱이 아닌 일반 앱에서 사용가능해 졌으니, 개인프로젝트의 플랫폼 선택에서 조금 더 자유로워 진 것 같다.

ExpandableMenu – WPF Custom Control

      ExpandableMenu – WPF Custom Control에 댓글 없음

1.개요

프로젝트 중 나중에 개인적으로도 사용할 만한 Custom Control 이 있어서 따로 정리하게 되었다.
물론 실제 프로젝트에 적용된 코드와 50% 이상 다르니.. 안심하고 ^^;

2. 요구사항

UX 팀에서 Microsoft Outlook 2008의 좌측 메뉴처럼 접혔다 펼쳐지는 메뉴를 원했다. 거기다가 펼쳐진 메뉴 이외의 메뉴들은 맨 하단으로 내려가게 되고, 전체 메뉴의 Height 크기는 변하지 않게 해달라고 하였다. 그리고 펼쳐지는 메뉴는 무조건 하나.

일반적으로 Expand 메뉴를 생각하면 StackPanel에 Expander Control을 여러 개 쌓고, Expander.Content의 Height 만큼 길이 제약이 없을테지만, 전체 컨트롤의 Height 크기만큼 유지 되어야 하는게 까다로웠다.

3. 개발

펼쳐지는 메뉴가 무조건 하나이기에 ListBox의 Single Select가 먼저 떠올랐다. Selector.IsSelected 프로퍼티에 Expander Control의 IsExpand 프로퍼티를 바인딩 시키면 하나만 펼쳐지기 때문이다.

3.1. ListBox Customizing

3.1.1. ListBoxItemContainerStyle

ListBox에 바인딩 될 메뉴는 ListBoxItem 으로 컨테이너가 생성되므로 Container의 Template를 수정한다.

ControlTemplate에 Expander 를 추가하고 Expander.Content에는 ContentPresenter를 두어 별도의 Template 설정을 가능하도록 한다.

그리고 Expander의 IsExpanded 프로퍼티에 ListBoxItem의 IsSelected 프로퍼티를 바인딩한다.

또한 Expander 의 Header 프로퍼티에 적당한 값이 들어가도록 바인딩한다. 나는 ExpandableMenu를 위하여 별도의 Class를 바인딩할 계획이므로 Header라는 프로퍼티에 바인딩하였다.

3.1.2. ItemTemplate

ListBox의 ItemTemplate부분에는 실제로 SubMenu 영역이 들어가게 될테지만, 여기서는 간단하게 알아볼 수 있을 정도로만 TextBlock 하나만 놓도록 하겠다.

3.2. Resize Expander.Content.Height

ListBoxItem이 선택되었을때, Expander 가 Expand 되는 것까지 확인하였다. 이제 Expander.Content 의 Height 크기를 조절해야 한다.

Code behind 로 가서 ListBox의 이것저것을 손보아야 한다.

ItemsControl.ItemContainerGenerator 를 이용하면 ListBoxItemContainer의 여러가지 상황에 따라 제어할 수 있다.

이 중 StatusChanged Event를 이용하여 컨테이너가 생성되어졌을때 Visual Parent인 TreeView의 ActualHeight를 구하고, 펼쳐지지 않은 Expander들의 Height를 구하여 ListBox에서 비어 있는 영역의 Height 를 Expander.Content의 Height로 설정한다.

아래는 주요 코드이다.

3.3. ExpandableMenuItem

뭐 특별한 거 없이 원하는 Header (Menu Name), Content (Sub-Menu Name)을 설정하기 위해 별도의 클래스를 만들어서 ListBox.ItemsSource에 바인딩하였다.

 

4. 정리

몇줄 안되는 코드로 멋진 컨트롤이 완성되었다. 여기에 추가적으로 블랜더가 스타일 좀 입히면 Telerik Control 부럽지 않는 Custom Control이 된다. 디자인 감각이 뛰어난 개발자라면 스스로 해보길 바란다. (난 디자인 감각이 없나봐 ㅠ)

전체 소스는 Github에 공개 하였다. 참고하길 바란다.

https://github.com/reastykim/ExpandableMenu

마을버스 배차 시간표 for Microsoft Band using WebTile – 2부

1. 개요

1부에서는 Band에  WebTile을 올려보았다. 조금 아쉬웠던 부분을 이글에서 마무리 하고자 한다.

1.1. 수정사항

  • 페이지 줄이기 – 평일에는 평일 시간표만, 휴일에는 휴일 시간표만.
  • 160자 제한 해결 – 현재 시간 기준으로 시간표 필터링.

위의 수정사항을 해결하기 위해서는 1부에서 사용했던 정적인 json 파일로는 어렵다. 따라서 동적인 Web 언어를 이용하여 json 파일을 생성하여 클라이언트로 내려주고자 한다.

애초에 간단하게 만들기가 목적이었기에, 별도의 서버 또는 서비스를 구축하지 않고, 현재 블로그를 실행하고 있는 WordPress에 php 파일을 하나 추가 생성하여 해결하기로 한다.

일단 난 Web은 잘 모른다. 더구나 php 는 1도 모른다. 이어지는 php 코드는 쌩초짜가 작성한 것임을 미리 밝힌다.

2. 수정

일단 HTTP Request에 대한 json Response을 반환하기위한 php파일을 생성한다. 그리고 기존의 json 파일을 객체화 시킨다.

2.1. 페이지 줄이기 – 평일에는 평일 시간표만, 휴일에는 휴일 시간표만.

평일과 휴일(일요일)을 구분하기 위해 아래의 함수를 추가한다. 추후 공휴일의 정보가 필요할 경우 ‘공공데이터포탈의 특일 정보제공 서비스 OpenAPI‘ 를 이용하기로 하고 지금은 단순히 일요일만 판단하기로 한다.

2.2. 160자 제한 해결 – 현재 시간 기준으로 시간표 필터링.

현재시간 이후의 배차시간표만 가져오기 위해 아래의 코드를 추가한다. 위에서 필터링한 $currentDays 배열에서 array_filter() 함수를 이용하여 다시 한번 필터링 한다.

2.3. 전체 소스

추가적으로 요청한 날짜와 시간을 표시하기 위해 몇가지 정보를 $currentDays 에 추가하였다. 아래는 전체 php 소스이다.

위의 소스를 웹서버에 Upload하고 실행하면 현재 요일, 시간기준으로 필터링된 배차시간표를 확인 할 수 있다.

3. 배포

배포절차는 기본적으로 1부에서 설명한 것과 같다. Step 2의 URL 을 위에서 작성한 php 링크로 변경한다. 그리고 Step 3에서 Assign your data에서 아래와 같이 Station, filteredTimesString을 데이터로 설정한다.

assignyourdata

그리고 webtile을 Download하여 Band의 WebTile을 실행하여 동작을 확인한다.

wp_20161124_16_17_49_pro

4. manifest.json 수정

버스 배차시간표의 간격은 최소 20분인데, WebTile의 기본 요청 주기는 30분이다. 이 부분을 수정하기 위해 *.webtile 파일의 확장자를 *.webtile.zip 으로 변경하여 manifest.json 파일을 변경해야 한다. manifest.json 파일의 refreshIntervalMinutes 값을 WebTile의 허용가능한 최소 값인 15로 변경한다. 그리고 버전 정보 또한 적당히 변경한다.

5. 마무리

다소 미비하고, 약간의 버그(토요일 막차시간이후 조회하는 경우, 공휴일이 아니라 평일 시간표를 가져옴)가 있지만 여기서 마무리 하고자 한다.

실제 테스트결과 요청시간에 따라 필터링 된 배차 시간표를 확인할 수 있었다. 하지만 변경한 refreshIntervalMinutes 값처럼 15분 마다 정확하게 업데이트 되지는 않았다. Microsoft 홈페이지에서는 어떠한 정보도 찾을 수 없었다. Band와 핸드폰의 Microsoft Band앱간의 Bluetooth 통신과 연결스펙인듯 하다. 아마 이부분은 WebTile의 한계점인것 같다.

Microsoft Band의 WebTile App을 하나 만들어 보았고, 더불어 PHP도 조금 건드려 본, 간단하지만 개인적으로 제법 의미있는 프로젝트였다.

간단한 RSS Feed 정도가 WebTile에 어울릴듯하고, 조금만 더 복잡한 로직이 필요하다면 Mobile App으로 Band SDK를 연동해야 할 것같다.

마을버스 배차 시간표 for Microsoft Band using WebTile – 1부

1. 개요

내가 가지고 있는 유일한 웨어러블 디바이스인 Microsoft Band2(이하 Band).
이걸 이용해서 뭔가 앱을 만들고 싶었는데 마땅한 아이디어가 생각나지 않았다.
(아이디어가 있어도 이미 나와있는 앱들이 많았다. 배경화면꾸미기라던지, 바코드 타일같은..)
Smart Band라고해도 결국 시계아닌가! 간단하게 마을버스 배차 시간표를 만들어보고자 한다.

2. 준비

2.1. 플랫폼 설정

Microsoft는 개발자들을 위해서 개발도구인 SDK를 제공한다.
글 쓰는 현재 시점에선 Cloud API를 제외하곤 SDK, WebTile의 지원이 중단된 상태이다.
no_longer_available
하지만 가장 최근에 릴리즈된 UWP, Xamarin SDK는 Nuget을 통하여 사용이 가능하다. 굳이 왜 지원을 중단했는지 아쉽다.
WebTile 또한 지원이 중단된 것으로 나오지만 WebTile의 Store역할을 하는 Gallery만 지원이 중단된 듯하고, “Get started” 버튼을 누르면 아직 사용이 가능하다.
getstarted
간단한 배차 시간표 App을 만들어 볼 생각이기 때문에 플랫폼을 WebTile로 설정하기로 한다.

2.1.1. Web Tile

개발관련 문서는 역시 Microsoft다. https://developer.microsoftband.com 이곳에서 12분12초짜리 WebTile Development Tutorial 동영상과 21페이지 짜리 WebTile Document 만 있으면Band WebTile 개발준비는 끝인것 같다.

2.2. 배차 시간표

일단 우리동네 마을버스(서울 광진02)는 운행거리가 짧아서 배차간격이나 실시간 위치정보까지도 필요없이(있으면 좋겠지만) 정해진 시간에 종점인 버스 정류소를 지난다.  배차시간표는 아래와 같이 제공된다. (급하게 찍느라 떨렸네;;)
wp_20161106_20_29_53_prowp_20161106_20_29_57_pro
WebTile을 만들기 위해선 json 또는 xml 이 필요하므로 위의 사진을 이용해서 간단히(라고 쓰고 노가다라고 읽는다) json파일을 작성해 보았다.

3. 개발

개발이라고 하기에도 민망하다. 위에서 준비한 json 파일을 웹서버에 올려두고 Tutorial에서 봤던대로 끌어다 놓고, 아이콘 이미지 추가하면 끝이다.

WebTile 개발자 사이트에서 “Get started” 버튼을 누르자.
webtiledev1

3.1. Choose a layout

webtiledev2
Band의 레이아웃을 선택하는 화면이다. 평일/공휴일별, 긴고랑/군자역의 시간표가 필요하기때문에 총 4페이지로 App을 구성하도록 한다. 그래서 Multiple page tile을 선택하고 화면은 시간이 여러줄 보여야하므로 Scrolling text wrap를 선택하고 Next 버튼을 클릭해서 다음 화면으로 넘어간다.

3.2. Submit your data

webtiledev3
위에서 만들어놓았던 json 파일을 웹서버에 업로드하고, 그 주소를 텍스트박스에 입력후 Next 버튼을 누른다.

3.3. Assign your data

webtiledev4
json 파일이 한글깨짐과 함께 멋지게(?) 파싱된다. 일단 한글문제는 놔두고, Tutorial에서 보았던 것처럼 원하는 항목을 Drag&Drop으로 채우면 된다.
조금 다른점이 있다면 빨간색으로 표시한 ‘1’과 ‘+’버튼이 보인다. Tutorial은 Single page로 했지만 난 Multi page로 레이아웃을 설정했기 때문이다.
왼쪽의 ‘+’버튼은 Band의 페이지를 추가하는 기능이고, 오른쪽의 ‘+’버튼은 Submit your data 페이지에서 보았던  json, xml을 추가하는 기능이다.
[평일-긴고랑, 평일-군자역,공휴일-긴고랑,공휴일-군자역] 이렇게 4개의 페이지를 구성하고 데이터를 채워넣어보았다.
webtiledev5

역시나 이 세상의 모든 문서는 빨간글씨와 작은 글씨를 맘에 세겨둬야 된다는 것을.. 새삼 느낀다 ㅠㅠ
160자 제한.. 시간표가 짤린다. 일단 이부분은 나중에 해결하기로 하고..
주황색박스는 직접타이핑해서 넣었고, 그 외 빨간색박스는 Drag&Drop으로 채웠다. Next 클릭으로 다음 화면으로 넘어간다.

3.4. Set up notification

webtiledev6
Tutorial에 있는 것 처럼 Notification(알림)은 필요없기에 Skip~

3.5. Give your tile an identity

webtiledev7

미리보기 화면이 상당히 불안(?)하기는 하지만 일단 app 만들기가 목표이므로…무시하고..
App의 테마는 Band의 기본설정을 따라적용되도록 미리보기화면의 아래 체크박스에 체크를 했다.
적당히 App의 정보를 입력한다. Name, Description, Creator, 그리고 적당한 Bus 아이콘을 웹에서 찾아서 추가하였다. 반드시(Must be) 46×46 픽셀의 transparent 배경의 png이미지를 추가하여야 한다고 한다.(까다롭네..) 이제 거의 끝난듯 하다. Next 클릭~

3.6. Download

webtiledev8

모든 개발과정(?)이 끝났다. ‘Download my tile’ 버튼을 누르면 ‘mytile.webtile’이라는 파일이 다운로드 시작된다. 적당한 이름(gwangjin02.webtile)으로 파일명을 바꾸고, Tutorial에서 보았던 것 처럼 메일이나 Web에 올려두고 Microsoft Band App이 설치된 핸드폰에서 실행하면 Band에 설치가 된다.

4. 설치

메일이나 웹 링크를 통하여 gwangjin02.webtile을 다운로드후 실행하면 아래와 같은 화면이 나온다.
실행하기 전에 이미 Microsoft Band App이 설치되어있어야 한다.
wp_ss_20161116_0001
위에서 입력한 타일 Icon, Name, Description, Author, 그리고 우리가 입력했던 Data source의 경로를 확인할 수 있다. Confirm 버튼을 누르면 ‘Adding a tile…’  메세지와 함께 Tile App이 Band에 설치된다.
wp_ss_20161116_0002
Microsoft Band App을 실행하여 타일관리 메뉴에 확인해보면 맨 아래쪽 ‘Tiles you added’ 카테고리에 방금 설치한 ‘광진02’ 타일이 등록되어 있다.
wp_ss_20161116_0003

5. 실행

이제 손목의 Band를 확인해 보면 내가 만든 Tile App의 아이콘이 떡하니 자리잡고 있다. 아 뿌듯해 ^-^
wp_20161116_20_41_14_pro
실행해보자.

…아, 시간이 짤린다…160자 제한…
뭐 그나마 다행인건, 한글이 깨지지 않는다는거!! 그리고 구현했던 4페이지 모두 정상적으로 보인다는거!!

2부에서는 앱을 좀더 가다듬어야 겠다.
첫째로 평일일때는 평일 배차시간표만, 휴일일때는 휴일배차시간표만 나오도록 하여 2페이로 줄이기.
두번째는 160자 제한이 걸리므로, 시간표의 내용을 줄이고, 좀더 가독성을 높이도록 수정하기.
일단 1부는 Band Tile App을 성공적으로 만들고 배포까지 했다는 것에 의의를 두기로 하고 2부에서 계속 진행하고자 한다.

Online Web Tools

      Online Web Tools에 댓글 없음

웹상에서 즉시 사용가능한 유용한 툴. 정말정말 자주 씀.

  1. Free Online Formatter – FreeFormatter (http://www.freeformatter.com)
    – 각종 포멧의 문자열을 들여쓰기하여 보여준다. Json, XML 디버깅시에 유용
  2. regexr.com (http://regexr.com)
    – 정규식을 테스트해 볼수 있으며, 유저들이 미리 만들어놓은 다양한 정규식을 참고가능
  3. Online Photo Editor (https://pixlr.com/editor)
    – 간단한 이미지 편집기
  4. Photopea (https://www.photopea.com)
    – 간단한 이미지 편집기2
  5. StackEditor (https://stackedit.io/editor)
    – *.md 파일(MarkDown) 편집기
  6. iConvert Icons (https://iconverticons.com)
    – image 파일로 아이콘 파일 생성

확장 메서드 (Extension method)

      확장 메서드 (Extension method)에 댓글 1개

확장 메서드는 C# 3.0부터 추가되었고, 대표적인 예로는 Linq가 있다. Linq의 대부분의(거의 모든) 메서드는 IEnumerable<T> 인터페이스의 확장 메서드로 구현되어 있다.

1. 구현

기본적인 구현방법은 class를 public static으로 선언하고, 메서드 역시 public static으로 선언하며, 확장하고자 하는 class Type 앞에 this 키워드를 붙여서서 선언한다. 구현부는 일반 메서드와 같다.
아래는 String에서 단어의 갯수를 반환해주는 간단한 예제다.

2. 사용

확장 메서드의 사용방법은 확장 메서드가 구현된 class의 Namespace를 using 절에 추가하여, 일반 멤버 메서드와 동일하게 사용가능하다. 해당 class의 intellisence에서는 (Extension) 이라는 키워드가 붙는거 이외엔 멤버 메서드와 동일하다. 아래는 위에서 구현한 확장 메서드의 사용 예제이다.

3. 주의사항

확장할 class의 멤버 메서드에 동일한 구조의 메서드가 있을 경우 호출 되지 않는다. 또한 Namespace 범위로 확장 메서드를 가져오게 되므로 호출하는 코드에서는 반드시 확장 메서드가 구현된 class의 Namespace를 using 절에 추가하여야 한다.

Microsoft C# 프로그래밍 가이드에서는 반드시 필요한 경우가 아니면 확장 메서드 대신에 class의 상속으로 구현하라고 가이드한다. 기존 class에 확장 메서드와 동일한 구조의 멤버 메서드가 추가되면 확장 메서드가 호출되지 않고 멤버 메서드가 호출되기 때문이다. 예제는 링크를 참조하기 바란다.

4. 의견

나는 주로 기존 클래스의 구조를 무너뜨리지 않으면서 필요한 기능을 확장하고 싶을때 사용한다. Util관련 메서드들을 확장 메서드로 구현하곤 한다. Namespace를 추가하면 간단하게 사용가능하기 때문이다. class의 상속도 하나의 방법이지만, 상속된 class가 증가함에 따라 각 class간의 결합도는 증가하기 때문에 되도록 상속을 피하고, 확장 메서드가 포함된 class를 별도의 라이브러리로 관리하여 코드의 재사용율을 높이는 편이다.

아래는 내가 자주사용하는 확장 메서드의 구현이다. 필요할 때마다 여러 프로젝트에 사용하고자 계속 업데이트할 계획이다.

5. 참고

https://msdn.microsoft.com/en-us/library/bb383977.aspx