UWP 다음 좌표 -> 주소 API .NET

저번에 GPS를 사용한 김에 갑자기 생각이 나서 쓰게 되었다

먼저 다음API 사이트에 접속을 해서 로컬에 들어간다.

다양한 API들이 있는데 여기서 좌표->주소 변환에 들어간다.

들어가면 설명이 있는데 무시하고 바로 사용법을 보자

일단 apikey를 발급 받는다. 발급 과정이 간단해서 좋은 것 같다.

바로 주소창에 예제대로 쳐본다. 참고로 나는 광화문의 좌표를 이용했다.
그럼 위의 창과 같이 나올텐데, 여기서 저 내용들을 복사한다.

그리고, 인터넷에 json2csharp이라는 사이트를 쳐서 들어간다.

해당사이트에 들어가서, 아까 복사해둔 내용을 붙혀넣는다.

Generate 버튼을 누르고 나오는 내용을 복사한다.

프로젝트를 하나 생성하고 그 안에 새로운 클래스를 하나 추가한다. 나는 AddressManager로 했다.

그 안에 아까 복사 해둔 내용을 붙혀넣는다. 이제 부턴 아래의 코드를 참고한다. 

AddressManager.cs

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;

namespace DaumAddressApiApp
{
class AddressManager
{
public async static Task<RootObject> GetAddress(double Latitude, double Longitude)
{
var Client = new HttpClient();
var JsonResponse = await Client.GetStringAsync("https://apis.daum.net/local/geo/coord2addr?apikey=0e7e5f413decd06b57472aa92f0818a5&longitude=" + Longitude + "&latitude=" + Latitude + "&output=json");
	    var Serializer = new DataContractJsonSerializer(typeof(RootObject));

var ms = new MemoryStream(Encoding.UTF8.GetBytes(JsonResponse));

var data = (RootObject)Serializer.ReadObject(ms);

return data;

}
}

[DataContract]
public class RootObject
{
[DataMember]
public string type { get; set; }
[DataMember]
public string code { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public string fullName { get; set; }
[DataMember]
public string regionId { get; set; }
[DataMember]
public string name0 { get; set; }
[DataMember]
public string code1 { get; set; }
[DataMember]
public string name1 { get; set; }
[DataMember]
public string code2 { get; set; }
[DataMember]
public string name2 { get; set; }
[DataMember]
public string code3 { get; set; }
[DataMember]
public string name3 { get; set; }
[DataMember]
public double x { get; set; }
[DataMember]
public double y { get; set; }
}
}

일단 먼저 웹에서 값을 가져오기 위해서 HttpClient를 하나 생성한다. 

그리고 값을 저장할 문자열을 하나 생성한다. 아까 예제에서의 url을 입력해주는데 위도와 경도를 입력받을 것이기 때문에 좌표부분은 인자로 대체한다.

Json 문자열을 우리가 사용할수 있게 바꿔주는 Serializer 변수를 하나 생성한다. 

여기서 Json 문자열이 RootObject 형식이기 때문에 인자로 typeof(RootObject)를 준다.

그 다음 MemoryStream을 하나 생성해서 Json문자열을 인코딩을 해서 저장한다.

MemoryStream형으로 한 이유는 Serializer.ReadObject의 인자가 Stream 형태이기 때문이다. 

이제 마지막으로, 값을 추출해서 리턴한다.

MainPage.xaml

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<Page
x:Class="DaumAddressApiApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DaumAddressApiApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBlock>현재좌표</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="Latitude"></TextBox>
<TextBox x:Name="Longitude"></TextBox>
<Button x:Name="Confirm" Click="Confirm_Click">조회</Button>
</StackPanel>
<TextBlock>현재주소</TextBlock>
<TextBlock x:Name="NowAdress"></TextBlock>
</StackPanel>
</Grid>
</Page>

대충 만들었다...

MainPage.xaml.cs

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// 빈 페이지 항목 템플릿에 대한 설명은 https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x412에 나와 있습니다.

namespace DaumAddressApiApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}

private async void Confirm_Click(object sender, RoutedEventArgs e)
{
RootObject rootObject = await AddressManager.GetAddress(double.Parse(Latitude.Text),double.Parse(Longitude.Text));
            NowAdress.Text = rootObject.fullname;
}
}
}

RootObject형으로 받아서 그 데이터의 fullname 값을 출력해줬다.

좌표가 약간 더 광화문 북쪽에 찍혀서 그런지 청운 효자동이 되었으나, 다른 건물을 대상으로 해보니 잘 나왔다...

UWP GPS .NET

먼저 위치정보를 앱에서 사용할수있도록 설정한다.

안드로이드 매니페스트처럼 UWP 프로젝트에도 Package.appxmanifest 가 있다.
기능탭의 위치 체크박스를 체크한다.

일단 GPS 값을 가져올 클래스를 하나 만들겠다. 딱히 안만들어도 되는데, 편하게 하기 위해서다.

LocationManager.cs  <== GPS 값을 가져올 클래스
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;

namespace LocationApp
{
class LocationManager
{
public static async Task<Geoposition> GetLocation() // 비동기 함수는 Task<T> 형태로 반환 해야함
{
var accessStatus = await Geolocator.RequestAccessAsync();

if (accessStatus != GeolocationAccessStatus.Allowed) throw new Exception();

var geolocator = new Geolocator();
geolocator.DesiredAccuracyInMeters = 0; // 위치서비스에서 반환된 데이터의 미터단위 정확도를 설정함

var position = await geolocator.GetGeopositionAsync();

return position;
}
}
}

GeolocationAccessStatus 옵션은 GPS 사용이 가능한지 불가능한지에 대한 옵션이다. 

여기서 발생하는 예외는 이 클래스에서 예외를 처리 하지 않고 상위 클래스로 던졌다.

Geolocaor 형 변수를 하나 생성하고, 정확도(오차범위)를 정해준다. 일단은 적은게 좋으니까 그냥 0 줬다.

위치를 구해서 Geoposition 형으로 리턴해 주는데, 비동기함수는 Task<T>(정확히는 Task<TResult>)의 형태로 리턴을 해주어야한다.

그래서, Task<Geoposition>형으로 리턴을 했다.

Main.xaml

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Page
x:Class="LocationApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LocationApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBlock>현재위치</TextBlock>
<TextBlock x:Name="NowLocation"></TextBlock>
</StackPanel>
</Grid>
</Page>

간단하다. 별로 출력할게 없었다.

Main.xaml.cs

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Devices.Geolocation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// 빈 페이지 항목 템플릿에 대한 설명은 https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x412에 나와 있습니다.

namespace LocationApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
GetPostion();
}
private async void GetPostion()
{
Geoposition postion = null;
try
{
postion = await LocationManager.GetLocation();
}
catch (Exception e)
{
Debug.WriteLine(e.StackTrace);
}
NowLocation.Text = postion.Coordinate.Latitude + " : " + postion.Coordinate.Longitude;
}
}
}

아까 상위클래스로 예외를 던져주었기 때문에 여기서 처리를 해주어야 한다.

Geoposition형으로 받아서 좌표를 TextBlock의 텍스트로 설정해주면 끝이다. Latitude가 위도, Longitude 경도이다.

실행결과


너무 상세한 내용이라고 생각이 들어서 몇부분 지웠습니다.

UWP MSSQL 연결 (3) .NET

저번에 이어 회원가입창을 만들어 보겠다.

회원 가입은 새로운 창을 열기 위해서 Page가 아닌 ContentDialog를 쓸 것이다.

나는 회원가입창의 이름을 「RegistrationDialog」 라고 했는데, 딱히 이름이 생각이 안 나서 그랬다... 매번 코딩할때 코딩보다 작명이 더 어려운 것 같다.

그 내부의 XAML파일에는 아래와 같이 작성해주자

<ContentDialog
x:Class="LoginApp.RegistrationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LoginApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Create Account"
PrimaryButtonText="Cancel"
SecondaryButtonText="Confirm"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
SecondaryButtonClick="ContentDialog_SecondaryButtonClick">

<Grid>
<StackPanel
<TextBlock>Name</TextBlock>
<TextBox x:Name="NameBox"
Margin="0 5 0 5"></TextBox>
<TextBlock>ID</TextBlock>
<TextBox x:Name="IDBox"
Margin="0 5 0 5"></TextBox>
<TextBlock>PW</TextBlock>
<PasswordBox x:Name="PWBox"
Margin="0 5 0 5"></PasswordBox>
</StackPanel>
</Grid>
</ContentDialog>

ContentDialog에 대해서 간단히 설명하면, 좀더 강화된 MessageDialog 라고 보면 된다.

ContentDialog는 기본적으로 하단에 버튼이 두개 있고, 왼쪽부터 Primary, Secondary 이다.

버튼의 Content를 변경할려면 ContentDialog의 속성에서 변경해야한다.

내부에는 이름, 아이디, 패스워드 입력창을 만들었다.

그럼 C# 파일을 보겠다.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// 콘텐츠 대화 상자 항목 템플릿에 대한 설명은 https://go.microsoft.com/fwlink/?LinkId=234238에 나와 있습니다.

namespace LoginApp
{
public sealed partial class RegistrationDialog : ContentDialog
{
HttpClient Client;
public RegistrationDialog()
{
this.InitializeComponent();
Client = new HttpClient();
}

private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
// Cancel버튼은 아무것도 하는 것이 없음
}

private async void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
Member AddMember = new Member()
{
Name = NameBox.Text,
ID = IDBox.Text,
PW = PWBox.Password
};

var MemberJson = JsonConvert.SerializeObject(AddMember);

var HttpContent = new StringContent(MemberJson);
HttpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

await Client.PostAsync("http://localhost:4872/api/MemberTables", HttpContent);
}
}
}

추가하는 부분은 참조하는 것 보다 조금 복잡하긴 하다.

저번에 만들어 놓은 Member 클래스 형 변수를 하나 생성해서, 입력창에서 입력받은 값들을 변수에 저장한다.

또, 새로운 변수를 만들어서 거기에 위의 변수를 Json형태로 바꿔서 저장한다. (코드에서는 귀찮아서 var 형으로 선언 했으나, string형 이다.)

Json으로 바꿔 저장한 문자열을 HttpClient.PostAsync 함수의 인자의 형식에 맞게 하기 위해서, StringContent형 변수를 하나더 생성한고 인자로 준다.

HttpContent의 Header에 ContentType을 application/json으로 설정한다. 우리가 json 방식을 사용했기 때문이다.

마지막으로, HttpClient에 Post방식으로 전송한다.

PostAsync 함수는 첫번째 인자는 URL이고 두번째 인자는 아까만든 HttpContent이다.

그럼 이제 테스트를 해보겠다.

위와 같이 정보를 입력했다.

잘 들어갔다. Index가 5인건 신경쓰지말자... python에서 request 연습용으로 잠깐 사용해서 그렇다.

이제 로그인을 해보겠다.

!성공!


※ 저번에 MainPage의 비밀번호 입력창과 위의 입력창의 모양이 약간 다른 것을 알 수 있는데, 비밀번호 입력에 특화된 PasswordBox를 사용했다.
PasswordBox는 [PasswordBox].Password 속성으로 입력된 정보를 가져올 수 있다. 저번에는 귀찮아서 그냥 했다.

UWP MSSQL 연결 (2) .NET

저번에 이어서 이번에는 UWP 앱을 만들어 볼거다.

웹프로젝트 이름을 LoginWebApp 이였으니까. UWP는 LoginApp으로 할거다. (이름은 알아서들 하시길)

프로젝트를 만들면 일단 UI부터 만들자.

<Page
x:Class="LoginApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LoginApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Margin="20 40 20 40">
<TextBlock HorizontalAlignment="Center"
FontSize="20dp">LOG IN</TextBlock>
<TextBlock>ID</TextBlock>
<TextBox x:Name="IDBox"
PlaceholderText="Your ID"></TextBox>
<TextBlock>PASSWORD</TextBlock>
<TextBox x:Name="PWBox"
PlaceholderText="Your PASSWORD"></TextBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Button x:Name="LoginButton"
Grid.Column="0"
Margin="20 20"
HorizontalAlignment="Stretch"
Click="LoginButton_Click">LogIn</Button>
<Button x:Name="RegistButton"
Grid.Column="1"
Margin="20 20"
HorizontalAlignment="Stretch"
Click="RegistButton_Click">Create Account</Button>
</Grid>
</StackPanel>
</Grid>
</Page>

대충 이렇게 만들었다. 

메인 라벨, 입력창이랑 라벨, 버튼 2개 끝.

그러면 이제 값을 가져와서 비교를 하는 방법을 알려주겠다.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace LoginApp
{
public sealed partial class MainPage : Page
{
HttpClient Client;

public MainPage()
{
this.InitializeComponent();
Client = new HttpClient();
}

private void RegistButton_Click(object sender, RoutedEventArgs e)
{
//회원가입은 나중에 할거임...
}

private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
var JsonResponse = await Client.GetStringAsync("http://localhost:4872/api/MemberTables");
var ResultList = JsonConvert.DeserializeObject<List<Member>>(JsonResponse);

foreach(var data in ResultList)
{
if(data.ID.Equals(IDBox.Text) && data.PW.Equals(PWBox.Text))
{
MessageDialog Success = new MessageDialog("!로그인 성공!");
await Success.ShowAsync();
}
else
{
MessageDialog Fail = new MessageDialog("!로그인 실패!");
await Fail.ShowAsync();
}
}
}
}
}

위의 코드를 보면 생성자 부분에서 HttpClient를 생성한 이유는 요청(request)을 보내기 위함이다.

LoginButton_Click 이벤트를 보면,

제일 처음 Client를 통해 요청을 보내고 그 응답(response)을 받는다. 습관상 var 형태로 해뒀는데 String형태로 들어온다. 

GetStringAsync 함수 인자에는 저번 포스트에서 봤던 API Help Page에서 Get방식을 사용하는 방법을 참고한다.

이제 웹에서 받은 결과값을 변환하는 과정을 거칠 것이다.

그런데, 그 전에 사전 작업이 필요하다.

일단 클래스를 하나 추가 한다.

Member.cs

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

namespace LoginApp
{
class Member
{
public int Index { get; set; }
public string ID { get; set; }
public string PW { get; set; }
public string Name { get; set; }
}
}

클래스에는 DB테이블의 컬럼 만들때 사용했었던 방법대로 

그대로 똑같이 만들어 준다. 단, Table 이름이나 Key는 설정 해줄 필요가 없다.

클래스를 만들면 다시 돌아가서 Json을 변환해주는 라이브러리를 설치한다.

저번과 같이 패키지 관리자 콘솔을 켜서 Install-Package NewtonSoft.Json 을 친다.

JsonConvert.DeserializeObject<T>() 함수는 <T> 에는 반환할 제네릭을 입력한다.

여기서 우리는 멤버들의 정보를 Member 클래스의 형태인 리스트로 받아올 것 이기 때문에, <List<Member>>라고 적었다.

괄호 안에는 변환할 문자열을 넣어준다. 우리는 JsonResponse를 사용해서 받아왔기 때문에 JsonResponse를 넣어줬다.

이번에도 변환된 데이터를 저장할 리스트를 만들때 var 형을 사용했는데, List를 사용해도 문제없다.

그 다음 foreach 문을 돌려서 리스트의 값을 갸져와 입력창에 들어 있는 값과 일치하면,

로그인 성공 메세지를 띄우고, 아니면 실패 메세지를 띄우게 했다.  


실행을 해보면,

잠깐! 실행 하기전에는 반드시 웹프로젝트도 실행시켜야 된다.

하지만, 두개 동시에 키기에는 번거롭다.

아래의 방법을 사용하자

일단 솔루션에 기존에 만들어 놓은 웹프로젝트를 추가한다.

추가했으면 다시 솔루션을 우클릭 해서 시작 프로젝트 설정을 누른다.  
여기서 두 프로젝트가 동시에 시작되게 설정한다.
위의 설정을 완료하고 시작 버튼을 누른다.
 
처음에는 올바른 정보를 입력했다.

로그인 성공이다.

이번에는 다른 비밀번호를 입력 했더니 로그인이 안 된다.

다음번에는 회원가입창을 만들어 보려 한다.

-끗-

UWP 팝업창 (2) Flyout .NET

MessageDialog는 앱 전체를 기준으로 하는 팝업창이라면 Flyout은 특정 컴포넌트을 기준으로 하는 팝업창이다.

역시 코드 부터 

MainPage.xaml

<Page
x:Class="FlyoutApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FlyoutApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"/>
<ColumnDefinition Width="0.3*"/>
<ColumnDefinition Width="0.3*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0.25*"/>
<RowDefinition Height="0.25*"/>
<RowDefinition Height="0.25*"/>
<RowDefinition Height="0.25*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Grid.Row="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
PointerEntered="TextBlock_PointerEntered">
이 것은 텍스트 블록입니다.
<FlyoutBase.AttachedFlyout>
<Flyout Placement="Bottom">
<TextBlock x:Name="TextBlockFlyout">This is TextBlock.</TextBlock>
</Flyout>
</FlyoutBase.AttachedFlyout>
</TextBlock>
<TextBox Grid.Column="1" Grid.Row="1"
PlaceholderText="이 것은 텍스트 박스입니다."
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
PointerEntered="TextBox_PointerEntered">
<FlyoutBase.AttachedFlyout>
<Flyout Placement="Right">
<TextBlock x:Name="TextBoxFlyout">This is TextBox.</TextBlock>
</Flyout>
</FlyoutBase.AttachedFlyout>
</TextBox>
<DatePicker Grid.Column="1" Grid.Row="2"
HorizontalAlignment="Stretch"
PointerEntered="DatePicker_PointerEntered">
<FlyoutBase.AttachedFlyout>
<Flyout Placement="Top">
<TextBlock x:Name="DatePickerFlyout">
This is DatePicker.
</TextBlock>
</Flyout>
</FlyoutBase.AttachedFlyout>
</DatePicker>
<Button Grid.Column="1" Grid.Row="3"
HorizontalAlignment="Stretch"
PointerEntered="Button_PointerEntered">
버튼
<FlyoutBase.AttachedFlyout>
<Flyout Placement="Full">
<TextBlock>
This is Button.
</TextBlock>
</Flyout>
</FlyoutBase.AttachedFlyout>
</Button>
</Grid>
</Page>

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace FlyoutApp
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}

private void TextBox_PointerEntered(object sender, PointerRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

private void TextBlock_PointerEntered(object sender, PointerRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

private void DatePicker_PointerEntered(object sender, PointerRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

private void Button_PointerEntered(object sender, PointerRoutedEventArgs e)
{
FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}
}
}

Flyout을 사용법은 다양하나, 나는 보통 Flyoutbase를 이용을 한다.

위의 xaml 파일에서와 같이 특정 컴포넌트의 태그 내부에 

<FlyoutBase.AttachedFlyout>
        <Flyout Placement="Right">
<TextBlock>This is Flyout.</TextBlock>
</Flyout>
</FlyoutBase.AttachedFlyout>

이런 식으로 Flyoutbase를 만들고 

Flyout을 추가하고 그 내부에 나타낼 컴포넌트를 넣는다.

위에서는 텍스트만 뿌려줄 것 이여서 TextBlock을 넣었지만, Button이나 TextBox 등 도 넣을 수 있다.

내부에 컴포넌트에 x:Name을 주면 일반 컴포넌트들과 같이 동일 한 방법으로 이벤트를 받을 수 있다.

그리고 Flyout이 상위 컴포넌트의 어느 곳에 띄워줄 것인가에 대해서 Placement라는 속성으로 정할 수 있다.

기본적으로 상,하,좌,우는 당연히 지원 되고, Full이라는 속성을 창을 가득 채워준다.

이제 cs 파일에서 Flyout을 띄우려면, 아래의 구문을 사용해야 한다.

FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);

저기서 sender는 Flybase의 상위 컴포넌트여야 한다.

EX) Button의 이름이 FlyoutBtn 일때, FlyoutBase.ShowAttachedFlyout(FlyoutBtn as FrameworkElement); 처럼 사용 가능하다.


1 2 3 4 5