Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
664 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
# Lab 3 - 讀取用戶的圖片瀏覽器 | ||
|
||
預估時間: **30 分鐘** | ||
|
||
## Lab 說明 | ||
|
||
透過這份 Lab 瞭解如何存取 App 套件內的檔案,以及使用 FileOpenPicker 讓用戶選擇要存取的檔案。 | ||
|
||
## 1. 開啟 Visual Studio 20015 並建立新專案 | ||
|
||
開啟 Visual Studio 2015,在啟始頁左側選擇_「新增專案...」_或是從上方功能表列選取_「檔案」_ » _「新增」_ » _「專案...」_。 | ||
|
||
![建立新專案](images/1-create-new-project.png) | ||
|
||
在新增專案的對話視窗中,在左側的範本中選擇 _「Visual C#」_ » _「Windows」_ » _「Windows Universal」_ ,然後選擇_「Blank App (Windows Universal)」_,最後再下方的名稱處輸入專案名稱,這裡使用 _LocalImageViewer_,完成後按下_確定_按鈕開始建立專案。 | ||
|
||
![建立空白 UWP App 專案](images/3-create-new-project.png) | ||
|
||
## 2. 設定操作介面 | ||
|
||
打開 **MainPage.xaml** 檔案,將 XAML 檔案內容修改為: | ||
|
||
```xml | ||
<Page | ||
x:Class="LocalImageViewer.MainPage" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:LocalImageViewer" | ||
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.RowDefinitions> | ||
<RowDefinition Height="120" /> | ||
<RowDefinition Height="*" /> | ||
</Grid.RowDefinitions> | ||
|
||
<TextBlock Grid.Row="0" Text="圖片瀏覽器" VerticalAlignment="Center" | ||
Style="{StaticResource HeaderTextBlockStyle}" Margin="20" /> | ||
|
||
<ScrollViewer Grid.Row="1"> | ||
<StackPanel Margin="20, 0"> | ||
<Button x:Name="OpenFileButton" Content="開啟檔案" Click="OpenFileButtonClicked" /> | ||
|
||
<Image x:Name="ImageTarget" Stretch="UniformToFill" Margin="0,20" /> | ||
</StackPanel> | ||
</ScrollViewer> | ||
|
||
</Grid> | ||
</Page> | ||
``` | ||
|
||
操作介面很簡單,就是一個按鈕讓使用者選擇要用什麼檔案來顯示,而 ```<Image />``` 元件就是用來顯示圖片使用的。 | ||
|
||
## 3. 將 Placeholder 圖片放入專案內 | ||
|
||
下載 [Placeholder 圖片](images/placeholder.png),然後放在專案內的 **Assets** 目錄下,記得在屬性設定中,將**複製到輸出目錄**設定成_永遠複製_、**建置動作**設成_內容_。 | ||
|
||
![加入 placeholer 圖片](images/3-add-placeholder.png) | ||
|
||
## 4. 在程式啟動時套上 Placeholder 圖片 | ||
|
||
打開 **MainPage.xaml.cs** 檔案,然後在建構式加入 ```Loaded``` 事件,並且在這事件的處理函式中讀取 placeholder 圖片然後放在 ```<Image />``` 元件上。 | ||
|
||
```csharp | ||
public MainPage() | ||
{ | ||
this.InitializeComponent(); | ||
|
||
Loaded += MainPage_Loaded; | ||
} | ||
|
||
private async void MainPage_Loaded(object sender, RoutedEventArgs e) | ||
{ | ||
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///Assets/placeholder.png")); | ||
using (var stream = await file.OpenAsync(FileAccessMode.Read)) | ||
{ | ||
var bitmap = new BitmapImage(); | ||
await bitmap.SetSourceAsync(stream); | ||
ImageTarget.Source = bitmap; | ||
} | ||
} | ||
``` | ||
|
||
在這裡我們可以看到如何使用 ```ms-appx:///``` 的 URI 形式來存取在 app 套件中的檔案。 | ||
|
||
## 5. 讓使用者選擇檔案 | ||
|
||
同樣地,我們在 **MainPage.xaml.cs** 檔案中加入畫面中按鈕的處理函式,並且在裡面使用 ```FileOpenPicker``` API 來讓使用者自行選擇圖片(副檔名為 jpg 的圖片)來顯示。 | ||
|
||
```csharp | ||
private async void OpenFileButtonClicked(object sender, RoutedEventArgs args) | ||
{ | ||
FileOpenPicker picker = new FileOpenPicker(); | ||
picker.ViewMode = PickerViewMode.Thumbnail; | ||
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; | ||
|
||
picker.FileTypeFilter.Add(".jpg"); | ||
|
||
StorageFile file = await picker.PickSingleFileAsync(); | ||
if (file != null) | ||
{ | ||
using (var stream = await file.OpenAsync(FileAccessMode.Read)) | ||
{ | ||
var bitmap = new BitmapImage(); | ||
await bitmap.SetSourceAsync(stream); | ||
ImageTarget.Source = bitmap; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
這裡我們使用 ```FileOpenPicker``` 物件,讓它以縮圖方式呈現檔案、建議從用戶的圖片目錄開始,然後在 ```FileTypeFilter``` 加上 ```.jpg``` 的描述,讓選擇檔案的對話盒只會顯示副檔名是 .jpg 結尾的檔案,取得檔案後就可以打開套用在 ```<Image />``` 元件上。 | ||
|
||
所以完整的 ```MainPage.xaml.cs``` 檔案會像是這樣: | ||
|
||
```csharp | ||
using System; | ||
using Windows.Storage; | ||
using Windows.Storage.Pickers; | ||
using Windows.UI.Xaml; | ||
using Windows.UI.Xaml.Controls; | ||
using Windows.UI.Xaml.Media.Imaging; | ||
|
||
namespace LocalImageViewer | ||
{ | ||
/// <summary> | ||
/// 可以在本身使用或巡覽至框架內的空白頁面。 | ||
/// </summary> | ||
public sealed partial class MainPage : Page | ||
{ | ||
public MainPage() | ||
{ | ||
this.InitializeComponent(); | ||
|
||
Loaded += MainPage_Loaded; | ||
} | ||
|
||
private async void MainPage_Loaded(object sender, RoutedEventArgs e) | ||
{ | ||
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///Assets/placeholder.png")); | ||
using (var stream = await file.OpenAsync(FileAccessMode.Read)) | ||
{ | ||
var bitmap = new BitmapImage(); | ||
await bitmap.SetSourceAsync(stream); | ||
ImageTarget.Source = bitmap; | ||
} | ||
} | ||
|
||
private async void OpenFileButtonClicked(object sender, RoutedEventArgs args) | ||
{ | ||
FileOpenPicker picker = new FileOpenPicker(); | ||
picker.ViewMode = PickerViewMode.Thumbnail; | ||
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; | ||
|
||
picker.FileTypeFilter.Add(".jpg"); | ||
|
||
StorageFile file = await picker.PickSingleFileAsync(); | ||
if (file != null) | ||
{ | ||
using (var stream = await file.OpenAsync(FileAccessMode.Read)) | ||
{ | ||
var bitmap = new BitmapImage(); | ||
await bitmap.SetSourceAsync(stream); | ||
ImageTarget.Source = bitmap; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio 14 | ||
VisualStudioVersion = 14.0.23107.0 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalImageViewer", "LocalImageViewer\LocalImageViewer.csproj", "{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|ARM = Debug|ARM | ||
Debug|x64 = Debug|x64 | ||
Debug|x86 = Debug|x86 | ||
Release|ARM = Release|ARM | ||
Release|x64 = Release|x64 | ||
Release|x86 = Release|x86 | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|ARM.ActiveCfg = Debug|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|ARM.Build.0 = Debug|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|ARM.Deploy.0 = Debug|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x64.ActiveCfg = Debug|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x64.Build.0 = Debug|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x64.Deploy.0 = Debug|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x86.ActiveCfg = Debug|x86 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x86.Build.0 = Debug|x86 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Debug|x86.Deploy.0 = Debug|x86 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|ARM.ActiveCfg = Release|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|ARM.Build.0 = Release|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|ARM.Deploy.0 = Release|ARM | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x64.ActiveCfg = Release|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x64.Build.0 = Release|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x64.Deploy.0 = Release|x64 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x86.ActiveCfg = Release|x86 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x86.Build.0 = Release|x86 | ||
{68B32EDA-9936-49C5-806A-9E71FC4FEDFD}.Release|x86.Deploy.0 = Release|x86 | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<Application | ||
x:Class="LocalImageViewer.App" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="using:LocalImageViewer" | ||
RequestedTheme="Light"> | ||
|
||
</Application> |
95 changes: 95 additions & 0 deletions
95
Projects/HOL3-LocalImageViewer/LocalImageViewer/App.xaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using System; | ||
using Windows.ApplicationModel; | ||
using Windows.ApplicationModel.Activation; | ||
using Windows.UI.Xaml; | ||
using Windows.UI.Xaml.Controls; | ||
using Windows.UI.Xaml.Navigation; | ||
|
||
namespace LocalImageViewer | ||
{ | ||
/// <summary> | ||
/// 提供應用程式專屬行為以補充預設的應用程式類別。 | ||
/// </summary> | ||
sealed partial class App : Application | ||
{ | ||
/// <summary> | ||
/// 初始化單一應用程式物件。這是第一行執行之撰寫程式碼, | ||
/// 而且其邏輯相當於 main() 或 WinMain()。 | ||
/// </summary> | ||
public App() | ||
{ | ||
this.InitializeComponent(); | ||
this.Suspending += OnSuspending; | ||
} | ||
|
||
/// <summary> | ||
/// 在應用程式由使用者正常啟動時叫用。當啟動應用 | ||
/// 將在例如啟動應用程式時使用以開啟特定檔案。 | ||
/// </summary> | ||
/// <param name="e">關於啟動要求和處理序的詳細資料。</param> | ||
protected override void OnLaunched(LaunchActivatedEventArgs e) | ||
{ | ||
|
||
#if DEBUG | ||
if (System.Diagnostics.Debugger.IsAttached) | ||
{ | ||
this.DebugSettings.EnableFrameRateCounter = true; | ||
} | ||
#endif | ||
|
||
Frame rootFrame = Window.Current.Content as Frame; | ||
|
||
// 當視窗中已有內容時,不重複應用程式初始化, | ||
// 只確定視窗是作用中 | ||
if (rootFrame == null) | ||
{ | ||
// 建立框架做為巡覽內容,並巡覽至第一頁 | ||
rootFrame = new Frame(); | ||
|
||
rootFrame.NavigationFailed += OnNavigationFailed; | ||
|
||
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) | ||
{ | ||
//TODO: 從之前暫停的應用程式載入狀態 | ||
} | ||
|
||
// 將框架放在目前視窗中 | ||
Window.Current.Content = rootFrame; | ||
} | ||
|
||
if (rootFrame.Content == null) | ||
{ | ||
// 在巡覽堆疊未還原時,巡覽至第一頁, | ||
// 設定新的頁面,方式是透過傳遞必要資訊做為巡覽 | ||
// 參數 | ||
rootFrame.Navigate(typeof(MainPage), e.Arguments); | ||
} | ||
// 確定目前視窗是作用中 | ||
Window.Current.Activate(); | ||
} | ||
|
||
/// <summary> | ||
/// 在巡覽至某頁面失敗時叫用 | ||
/// </summary> | ||
/// <param name="sender">導致巡覽失敗的框架</param> | ||
/// <param name="e">有關巡覽失敗的詳細資料</param> | ||
void OnNavigationFailed(object sender, NavigationFailedEventArgs e) | ||
{ | ||
throw new Exception("Failed to load Page " + e.SourcePageType.FullName); | ||
} | ||
|
||
/// <summary> | ||
/// 在應用程式暫停執行時叫用。應用程式狀態會儲存起來, | ||
/// 但不知道應用程式即將結束或繼續,而且仍將記憶體 | ||
/// 的內容保持不變。 | ||
/// </summary> | ||
/// <param name="sender">暫停之要求的來源。</param> | ||
/// <param name="e">有關暫停之要求的詳細資料。</param> | ||
private void OnSuspending(object sender, SuspendingEventArgs e) | ||
{ | ||
var deferral = e.SuspendingOperation.GetDeferral(); | ||
//TODO: 儲存應用程式狀態,並停止任何背景活動 | ||
deferral.Complete(); | ||
} | ||
} | ||
} |
Binary file added
BIN
+1.4 KB
...ects/HOL3-LocalImageViewer/LocalImageViewer/Assets/LockScreenLogo.scale-200.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+7.52 KB
Projects/HOL3-LocalImageViewer/LocalImageViewer/Assets/SplashScreen.scale-200.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.87 KB
...s/HOL3-LocalImageViewer/LocalImageViewer/Assets/Square150x150Logo.scale-200.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.61 KB
...cts/HOL3-LocalImageViewer/LocalImageViewer/Assets/Square44x44Logo.scale-200.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.23 KB
...ewer/LocalImageViewer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+3.13 KB
...cts/HOL3-LocalImageViewer/LocalImageViewer/Assets/Wide310x150Logo.scale-200.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+16.1 KB
Projects/HOL3-LocalImageViewer/LocalImageViewer/Assets/placeholder.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.