- 전체
- Native Apps
- WinJS App
- C# Apps
- XAML
- VB.net
- VisualC.net
- C++
- MFC
- visual studio mobile app dev
- Azure ms cloud service
- Asp.net
- 인공지능 (AI)
- wpf
- UWP
- MAUI
- asp.net
C++ C++ Windows 스토어 앱에서 파일 선택기 사용(자습서 4/4)
2014.05.30 15:22
[출처] http://msdn.microsoft.com/ko-kr/library/windows/apps/dn263165.aspx
C++ Windows 스토어 앱에서 파일 선택기 사용(자습서 4/4)
C++ 자습서 시리즈의 이 부분에서는 사용자가 파일을 가져오고, 데이터에 UI 컨트롤을 바인딩하고, 이전에 열었던 파일에 액세스할 수 있게 MostRecentlyUsedList를 구현할 수 있도록 FileOpenPicker를 추가하는 방법을 설명합니다.
이 시리즈의 두 번째 자습서인 앱 수명 주기 및 상태 관리에서는 앱 데이터 및 세션 데이터와 이 데이터를 ApplicationData 저장소에 저장하는 방법에 대해 알아보았습니다. 앱은 기본적으로 앱 데이터 위치, 앱 설치 디렉터리 같은 특정 파일 위치와 앱이 Downloads 폴더에 만드는 항목에 액세스할 수 있습니다.
이와 달리 사진, 동영상, 문서 파일 등 사용자 데이터는 앱과 독립적이며 일반적으로 사용자의 라이브러리 폴더나 파일 시스템의 다른 위치에 저장됩니다. 이러한 위치에 액세스하려면 앱은 데이터에 액세스하기 위한 기능을 프로그래밍 방식으로 선언하거나, 사용자가 직접 파일을 열 수 있도록 파일 선택기를 포함해야 합니다. 여기서는 파일 선택기를 사용하여 사용자의 사진 라이브러리에 액세스하므로 앱 기능을 선언하지 않아도 됩니다. 기능에 대한 자세한 내용은 앱 기능 선언을 참조하세요.
이 자습서에서 학습할 내용은 3부: 탐색, 레이아웃 및 보기에서 만든 사진 페이지 레이아웃에 기능을 추가하는 것입니다. 먼저, 사용자가 사진 라이브러리에서 이미지를 선택할 수 있도록 "Get photo(사진 가져오기)" 단추 클릭 이벤트를 처리하여 파일 선택기를 엽니다. 그런 다음 UI 컨트롤을 파일 속성에 바인딩하여 그림 정보를 표시합니다. 마지막으로 앱 상태를 저장하는 방법에 대해 두 번째 자습서에서 학습한 내용을 복습합니다. MostRecentlyUsedList를 사용하여 사용자가 선택한 이미지에 대한 액세스를 유지합니다.
시작하기 전에...
- 이 자습서는 시리즈 중 네 번째 자습서입니다. 시작하기 전에 Hello World(C++), 앱 수명 주기 및 상태 관리(C++) 및 탐색, 레이아웃 및 보기(C++)를 읽어보세요.
- 이 자습서의 전체 코드는 코드 갤러리의 Hello World(C++) 샘플에서 확인할 수 있습니다.
1단계: 파일 선택기를 사용하여 이미지 파일 선택
파일 선택기를 통해 앱은 사용자 선택에 따라 사용자 시스템 전체의 파일 및 폴더에 액세스할 수 있습니다. 파일 선택기를 호출하면 사용자가 파일 또는 폴더를 찾아 액세스하고 저장할 수 있습니다. 사용자가 파일이나 폴더를 선택하면 앱은 해당 선택 항목을 StorageFile 및 StorageFolder 개체로 받습니다. 그런 다음 앱은 해당 개체를 사용하여 선택한 파일 및 폴더에서 작업할 수 있습니다.
가장 먼저 해야 할 일은 GetPhotoButton_Click 이벤트를 처리하여 표시할 그림을 가져오는 것입니다.
여기서는 탐색, 레이아웃 및 보기(C++)의 코드로 시작하겠습니다.
파일 선택기를 추가하려면
- 솔루션 탐색기에서 PhotoPage.xaml를 엽니다.
- "사진 가져오기" Button를 선택합니다.
- 속성 창에서 이벤트 단추(
)를 선택합니다. - 이벤트 목록에서 Click 이벤트를 찾습니다. 해당 이벤트의 텍스트 상자에 Click 이벤트를 처리하는 메서드의 이름을 "GetPhotoButton_Click"으로 입력합니다.
- Enter 키를 누릅니다. 이벤트 처리기 메서드가 PhotoPage.xaml.cpp에서 만들어지고 이벤트 발생 시 실행될 코드를 추가할 수 있도록 코드 편집기에서 열립니다.
- 다음 코드를 이벤트 처리기 메서드에 추가합니다. 사용자가 사진 라이브러리에서 사진을 선택할 수 있는 파일 선택기가 열립니다. 사용자가 파일을 선택하면 파일이 이미지의 원본 및 페이지의 데이터 컨텍스트로 설정됩니다.
auto openPicker = ref new Windows::Storage::Pickers::FileOpenPicker(); openPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::PicturesLibrary; openPicker->ViewMode = Windows::Storage::Pickers::PickerViewMode::Thumbnail; // Filter to include a sample subset of file types. openPicker->FileTypeFilter->Clear(); openPicker->FileTypeFilter->Append(".bmp"); openPicker->FileTypeFilter->Append(".png"); openPicker->FileTypeFilter->Append(".jpeg"); openPicker->FileTypeFilter->Append(".jpg"); // Open the file picker. create_task(openPicker->PickSingleFileAsync()).then( [this](Windows::Storage::StorageFile^ file) { // file is null if user cancels the file picker. if (file != nullptr) { // Open a stream for the selected file. create_task([file]() { // asynchronously return the IRandomAccessStream^ object return file->OpenAsync(Windows::Storage::FileAccessMode::Read); }).then([this, file](Windows::Storage::Streams::IRandomAccessStream^ fileStream) { // Set the image source to the selected bitmap. Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); bitmapImage->SetSource(fileStream); displayImage->Source = bitmapImage; this->DataContext = file; }); } });
- PhotoPage.xaml.cpp의 맨 위에 다음 using 문을 추가합니다.
- F5 키를 눌러 앱을 빌드 및 실행합니다. 사진 페이지로 이동하고 "사진 가져오기" 단추를 선택하여 FileOpenPicker를 실행합니다. 사진 선택기에서 사진을 선택한 다음 열기 단추를 선택합니다. 해당 사진이 사진 페이지에 표시되지만 사진 정보 텍스트는 업데이트되지 않습니다. 다음 단계에서 이 부분을 설정합니다.
선택한 사진이 표시된 앱의 모양은 다음과 같습니다.
이제 FileOpenPicker에 대한 코드를 좀 더 면밀하게 살펴보겠습니다. 파일 선택기를 사용하려면 파일 선택기 개체를 만들고 사용자 지정하며, 사용자가 항목을 선택할 수 있도록 파일 선택기를 표시해야 합니다.
먼저 FileOpenPicker 개체를 만듭니다.
사용자 및 앱과 관련된 파일 선택기 개체에서 속성을 설정합니다. 파일 선택기 사용자 지정 방법을 결정하는 데 도움이 되는 지침은 파일 선택기에 대한 지침을 참조하세요.
사용자가 사진을 선택하므로 SuggestedStartLocation을 사진 라이브러리로, ViewMode를 Thumbnail로 설정합니다. 또한 선택기에 지정된 이미지 파일 유형만 표시되도록 필터를 추가합니다.
openPicker->SuggestedStartLocation = Windows::Storage::Pickers::PickerLocationId::PicturesLibrary;
openPicker->ViewMode = Windows::Storage::Pickers::PickerViewMode::Thumbnail;
// Filter to include a sample subset of file types.
openPicker->FileTypeFilter->Clear();
openPicker->FileTypeFilter->Append(".bmp");
openPicker->FileTypeFilter->Append(".png");
openPicker->FileTypeFilter->Append(".jpeg");
openPicker->FileTypeFilter->Append(".jpg");
파일 선택기를 만들고 사용자 지정한 후 사용자가 파일 하나를 선택할 수 있도록 하려면 비동기 메서드 중 하나인 FileOpenPicker::PickSingleFileAsync를 호출해야 합니다. C++에서는 concurrency::create_task 메서드를 사용하여 비동기 메서드를 호출합니다. 이 메서드는 모든 C++ 프로젝트의 pch.h 헤더 파일에 포함된 ppltasks.h에 정의되어 있습니다. .then 메서드는 continuation이라고 하며 create_task 본문에서 코드가 완성될 때 실행됩니다. create_task에서 반환된 값이 괄호로 묶인 입력 매개 변수로서 전달되며, 주변 컨텍스트의 변수는 각괄호로 캡처됩니다. 람다 식에서 멤버 변수를 참조하고자 하기 때문에 종종 "이것"을 캡처해야 합니다.
참고 선택한 여러 개의 파일을 사용하려면 PickMultipleFilesAsync를 호출합니다.
// Open the file picker. create_task(openPicker->PickSingleFileAsync()).then( [this](Windows::Storage::StorageFile^ file) { // file is null if user cancels the file picker. if (file != nullptr) { // Open a stream for the selected file. create_task([file]() { // asynchronously return the IRandomAccessStream^ object return file->OpenAsync(Windows::Storage::FileAccessMode::Read); }).then([this, file](Windows::Storage::Streams::IRandomAccessStream^ fileStream) { // Set the image source to the selected bitmap. Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); bitmapImage->SetSource(fileStream); displayImage->Source = bitmapImage; this->DataContext = file; }); } });
사용자가 파일을 선택하면 PickSingleFileAsync는 선택된 파일을 나타내는 StorageFile 개체를 반환합니다. 이미지 스트림을 처리하여 BitmapImage를 만들고 UI에서 BitmapImage를 Image 컨트롤의 Source로 설정합니다. 또한 UI 요소를 속성에 바인딩할 수 있도록 파일을 페이지의 DataContext로 설정합니다.
2단계: 파일 데이터에 UI 컨트롤 바인딩
이제 UI에 이미지가 표시됩니다. 그렇지만 이미지 파일 속성은 앞서 추가한 텍스트 블록에 아직 표시되지 않습니다.
Image.Source 속성을 설정한 것처럼, 코드에서 각 TextBlock의 Text 속성을 설정할 수 있습니다. 그러나 데이터를 표시하려면 일반적으로 Binding.Source 속성을 설정하거나 UI 요소에 DataContext를 설정함으로써 데이터 바인딩을 사용하여 데이터 원본을 UI에 연결합니다. 바인딩을 설정한 후 데이터 원본이 변경될 경우 데이터 원본에 바인딩된 UI 요소는 변경 내용을 자동으로 반영합니다.
참고 기본적으로 바인딩은 one-way입니다. 즉, 데이터 원본 업데이트가 UI에 반영됩니다. two-way 바인딩을 지정하면 사용자가 UI 요소를 변경할 경우 해당 사항이 데이터 원본에 반영되게 할 수 있습니다. 예를 들어, 사용자가 TextBox에서 값을 편집할 경우 바인딩 엔진은 기본 데이터 원본을 자동으로 업데이트하여 변경 내용을 반영합니다.
이 자습서에서는 DataContext 속성을 사용하여 전체 UI 요소 및 모든 자식 요소에 대한 기본 바인딩을 설정합니다. FileOpenPicker에서 선택한 StorageFile을 사진 페이지의 DataContext로 설정합니다. 앞의 코드에서 이미지를 선택한 후 다음 줄을 사용하여 DataContext를 설정해야 합니다.
제목 TextBlock의 Text 속성을 선택한 파일의 StorageFile.DisplayName 속성에 바인딩하여 파일 이름을 표시합니다.
바인딩 Source는 지정하지 않으므로 데이터 바인딩 엔진이 DataContext에서 DisplayName 속성을 찾습니다. DataContext가 null이거나 DisplayName 속성을 갖지 않으면 자동으로 바인딩이 실패하고 TextBlock에 텍스트가 표시되지 않습니다.
여기에서는 TextBlock 컨트롤을 StorageFile 속성에 바인딩합니다.
데이터에 UI 컨트롤을 바인딩하려면
- 솔루션 탐색기에서 PhotoPage.xaml를 엽니다.
- "사진 가져오기" 단추 아래에 있는 사진 이름에 대한 TextBlock을 선택합니다.
- 속성 창에서 속성 단추(
) 를 선택하여 속성 보기를 표시합니다. - 속성 창의 공통 아래에서 Text 속성에 대해 속성 마커를 선택합니다. 속성 메뉴가 열립니다.
참고 속성 마커는 각 속성 값의 오른쪽에 있는 작은 상자 기호입니다. Text 속성 마커는 문자열 값으로 설정되었음을 나타내는 검은색입니다.
- 속성 메뉴에서 데이터 바인딩 만들기를 선택합니다. 데이터 바인딩 만들기 대화 상자가 열립니다.
- 대화 상자의 바인딩 형식 드롭다운 목록에서 데이터 컨텍스트를 선택합니다.
- 아래와 같이 경로 텍스트 상자에 "DisplayName"을 입력합니다.
참고 데이터 바인딩 만들기 대화 상자에 데이터 컨텍스트가 설정되지 않았다는 메시지가 표시됩니다. 앱을 실행하고 사진을 가져올 때 코드에서 데이터 컨텍스트를 설정할 것이므로 이 메시지는 무시해도 좋습니다.
- 확인 단추를 선택합니다.
다음은 바인딩을 추가한 후 TextBlock에 대한 XAML(Extensible Application Markup Language)입니다.
- "파일 이름:"TextBlock 뒤에 있는 TextBlock을 선택합니다.
- 3-5단계를 반복하여 이 TextBlock에 대한 데이터 바인딩을 만듭니다.
- 경로 텍스트 상자에 "이름"을 입력하고 확인을 클릭합니다.
- "경로:" TextBlock 뒤에 있는 TextBlock을 선택합니다.
- 3-5단계를 반복하여 이 TextBlock에 대한 데이터 바인딩을 만듭니다.
- 경로 텍스트 상자에 "경로"를 입력하고 확인을 선택합니다.
다음은 바인딩을 추가한 후 사진 정보 StackPanel에 대한 XAML입니다.
<StackPanel Margin="20,0,0,0"> <TextBlock TextWrapping="Wrap" Text="File name:" Style="{StaticResource CaptionTextBlockStyle}"/> <TextBlock TextWrapping="Wrap" Text="{Binding Name}" Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,30"/> <TextBlock TextWrapping="Wrap" Text="Path:" Style="{StaticResource CaptionTextBlockStyle}"/> <TextBlock TextWrapping="Wrap" Text="{Binding Path}" Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,30"/> </StackPanel>
- F5 키를 눌러 앱을 빌드 및 실행합니다. 사진 페이지로 이동합니다. "사진 가져오기" 단추를 클릭하여 FileOpenPicker를 실행합니다. 바인딩이 준비되어 있으므로 이제 파일을 선택하면 파일 속성이 표시됩니다.
사진이 선택되어 있고 텍스트 블록이 데이터에 바인딩된 앱의 모양은 다음과 같습니다.
3단계: 상태 저장 및 로드
이 시리즈의 두 번째 자습서인 앱 수명 주기 및 상태 관리에서는 앱 상태를 저장하고 복원하는 방법에 대해 알아보았습니다. 이제 앱에 새 페이지를 추가했으므로 새 페이지의 상태도 저장하고 로드해야 합니다. 사진 페이지의 경우에는 현재 표시되는 이미지 파일만 저장하고 복원하면 됩니다.
그러나 파일의 경로를 저장한 다음 해당 경로를 사용하여 파일을 다시 열 수는 없습니다. 사용자가 FileOpenPicker를 사용하여 파일을 선택하는 경우 해당 파일을 사용할 수 있는 권한을 앱에 암시적으로 부여합니다. 그러나 나중에 경로만 사용하여 파일을 검색하려고 하면 사용 권한이 거부됩니다.
대신 파일에 대한 액세스 권한을 유지하여 나중에 사용할 수 있도록, StorageApplicationPermissions 클래스는 파일 및 사용자가 파일 선택기로 이 파일을 열었을 때 부여된 권한을 저장할 수 있는 목록 두 개를 제공합니다.
- MostRecentlyUsedList - 최근에 액세스한 25개 파일을 저장합니다.
- FutureAccessList - 이후 액세스를 위해 최대 1000개의 파일을 저장하는 일반 저장소입니다.
여기서는 사용자가 선택한 마지막 파일에만 액세스해야 하므로 페이지 상태를 복원하는 데 사용할 수 있습니다. 따라서 MostRecentlyUsedList가 요구 사항을 충족합니다.
사용자가 파일을 선택하면 이를 MostRecentlyUsedList에 추가합니다. 이 목록에 파일을 추가하면 MostRecentlyUsedList는 나중에 해당 파일을 검색하는 데 사용할 수 있는 토큰을 반환합니다. 이 토큰을 pageState 사전에 저장하고, 페이지 상태를 복원할 때 현재 이미지 파일을 검색하는 데 사용합니다.
상태를 저장하려면
- 솔루션 탐색기에서 PhotoPage.xaml.h를 엽니다. 아래에 있는 두 개의 코드 숨김 파일을 표시하려면 PhotoPage.xaml 노드를 확장해야 할 수 있습니다.
PhotoPage클래스에서 다음 비공개 변수를 추가합니다. 이것은 MostRecentlyUsedList에서 반환하는 토큰을 유지하기 위한 변수를 선언합니다.- PhotoPage.xaml.cpp에서 마지막 내부 then 메서드에 대한 continuation으로 다음 코드를
GetPhotoButton_Click이벤트 처리기에 추가합니다(마지막 문은this->DataContext = file). 이 코드는 선택한 파일을 MostRecentlyUsedList에 추가하고 토큰을 가져옵니다..then([this, file]() { // Add picked file to MostRecentlyUsedList. mruToken = Windows::Storage::AccessCache::StorageApplicationPermissions::MostRecentlyUsedList->Add(file); })
다음은 주변 코드가 있는 코드입니다.
// Open the file picker. create_task(openPicker->PickSingleFileAsync()).then( [this](Windows::Storage::StorageFile^ file) { // file is null if user cancels the file picker. if (file != nullptr) { // Open a stream for the selected file. create_task([file]() { return file->OpenAsync(Windows::Storage::FileAccessMode::Read); }).then([this, file](Windows::Storage::Streams::IRandomAccessStream^ fileStream) { // Set the image source to the selected bitmap. Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); bitmapImage->SetSource(fileStream); displayImage->Source = bitmapImage; this->DataContext = file; }).then([this, file]() { // Add picked file to MostRecentlyUsedList. mruToken = Windows::Storage::AccessCache::StorageApplicationPermissions::MostRecentlyUsedList->Add(file); }); } });
PhotoPage::SaveState메서드에 다음 코드를 추가합니다. 토큰이 있는지 확인하고, 토큰이 있으면PageState사전에 토큰을 저장합니다.if (mruToken != nullptr && !mruToken->IsEmpty()) { e->PageState->Insert("mruToken", mruToken); }
다음은
navigationHelper_SaveState메서드에 대한 전체 코드입니다.
상태를 로드하려면
- PhotoPage.xaml.cpp에서 다음 코드를
PhotoPage::LoadState메서드에 추가합니다.여기서는
PageState디렉터리에서 토큰을 가져오고, 이 토큰을 사용하여 MostRecentlyUsedList에서 파일을 검색한 다음 UI 상태를 복원합니다.if (e->PageState != nullptr && e->PageState->HasKey("mruToken")) { Object^ value = e->PageState->Lookup("mruToken"); if (value != nullptr) { mruToken = value->ToString(); // Open the file via the token that you stored when adding this file into the MRU list:: create_task(Windows::Storage::AccessCache::StorageApplicationPermissions::MostRecentlyUsedList->GetFileAsync(mruToken)) .then([this](Windows::Storage::StorageFile^ file) { if (file != nullptr) { // Open a stream for the selected file-> // Windows.Storage->Streams.IRandomAccessStream fileStream = create_task(file->OpenAsync(Windows::Storage::FileAccessMode::Read)) .then([this, file](Windows::Storage::Streams::IRandomAccessStream^ fileStream) { // Set the image source to a bitmap. auto bitmapImage = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(); bitmapImage->SetSource(fileStream); displayImage->Source = bitmapImage; // Set the data context for the page-> this->DataContext = file; }); } }); } }
- F5 키를 눌러 앱을 빌드 및 실행합니다. 사진 페이지로 이동하고 "사진 가져오기" 단추를 선택하여 FileOpenPicker를 실행한 다음 파일을 선택합니다. 이제부터는 앱이 일시 중단, 종료 및 복원될 때 이미지가 다시 로드됩니다.
참고 앱 일시 중단, 종료 및 복원 방법에 대해서는 앱 수명 주기 및 상태 관리를 참조하세요.
요약
축하합니다! Windows 스토어 앱에서 파일 선택기 및 데이터 바인딩을 사용하는 방법을 알아본 네 번째 자습서를 마쳤습니다.
코드 보기
난관에 봉착했나요? 또는 작업의 확인이 필요하세요? 코드 갤러리의 Hello World(C++) 샘플을 참조하세요.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

