使用者自訂對話窗與PopUp應用 頁面
目的
在這篇文章中,將會說明如何客製一個使用者對話窗,並且產生一個頁面遮罩,讓這個對話窗顯示在原來頁面之上。
學習重點
在這個練習專案中,將會讓您學會底下技能與方法的使用:
- 使用
ContentView
產生許多使用者控制項 (User Control),可以反覆使用的控制項 - 如何在相關頁面之中,引用這些新建立的使用者控制項
- 使用檢視模型 (ViewModel) 來控制使用者控制項顯示與否和進行資料繫結
- 如何處理與回應使用者控制項中的相關事件或者 ICommand
- 使用顏色來表示螢幕遮罩的方法
- 讀取使用者控制項所輸入或者回應的資料和訊息
- 在 XAML 內,使用手勢操作(
GestureRecognizers
)判斷使用者點選使用者控制項,以便中止顯示該控制項
專案原始碼
專案使用到的圖片
無
實作方法
建立專案
- 在
Visual Studio 2015
,點選功能表檔案
>新增
>專案
- 在
新增專案
對話窗內,點選範本
>Visual C#
>Prism
>Prism Unity App (Forms)
- 在底下名稱欄位中,輸入
CustomDiag
最後,點選確定
按鈕。 - 當出現
Prism for Xamarin.Forms - Project Wizard
對話窗,請勾選Android
,iOS
,UWP
這三個選項,表示您想要產生使用 Prism 框架的這三種原生 Xamarin.Forms 專案,最後點選Create
按鈕。
當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。
- 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
若您無法看到 Prism 項目,用來建立 Prism 類型專案,那可能是您的 Visual Studio 2015 內沒有安裝Prism Template Pack
擴充功能,請參考 附件 : 使用 Visual Studio 2015 增加 Prism 專案樣版
- 滑鼠右擊
CustomDiag.Droid
,選擇設定為起始專案
- 展開
CustomDiag.Droid
>Properties
,滑鼠雙擊Properties
這個節點 - 在標籤頁次
Application
,選擇項目Minimum Android to target
的下拉選單,選擇值為Android 4.4 (API Level 19 - Kit Kat)
這個選項,接著按下Ctrl + S
組合案件,儲存此次修改設定。 - 滑鼠右擊
CustomDiag.Droid
,選擇建置
進行專案編譯
開發前準備工作
建立資料夾
- 請在核心PCL 專案內,建立一個
UserControls
資料夾
複製專案使用的圖片檔案
無
專案開發
建立 CustDialogUserControl 使用者控制項 (User COntrol)
- 滑鼠右擊核心PCL專案的
UserControls
資料夾,選擇加入
>新增項目
- 在對話窗點選
Visual C#
>Cross-Platform
>Forms Xaml Page
- 在名稱欄位輸入
CustDialogUserControl
,接著點選新增
按鈕 - 將底下 XAML 標記宣告複製到剛剛建立的檔案內
CustDialogUserControl.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomDiag.UserControls.CustDialogUserControl">
<!--<ScrollView
Orientation="Vertical"
VerticalOptions="Fill" HorizontalOptions="Fill"
>
</ScrollView>-->
<Grid
HorizontalOptions="Fill" VerticalOptions="Fill"
>
<BoxView
BackgroundColor="#BB000000"
/>
<BoxView
BackgroundColor="#FFFFFFFF"
Margin="20,70"
/>
<StackLayout
Margin="40,80"
HorizontalOptions="Fill" VerticalOptions="Start"
>
<Label
Text="{Binding 客製化使用者對話窗ViewModel.對話窗主題}"
TextColor="#000000"
FontSize="30"
HorizontalOptions="Center"
Margin="0,40,0,20"
/>
<Label
Text="{Binding 客製化使用者對話窗ViewModel.對話窗訊息}"
TextColor="#000000"
Margin="20,20,20,30"
FontSize="18"
HorizontalTextAlignment="Center"
HorizontalOptions="Center"
/>
<Label Text="帳號" />
<Entry
HorizontalOptions="Fill"
Text="{Binding 客製化使用者對話窗ViewModel.對話窗使用者帳號}"
/>
<Label Text="密碼" />
<Entry
HorizontalOptions="Fill"
Text="{Binding 客製化使用者對話窗ViewModel.對話窗使使用者密碼}"
IsPassword="True"
/>
<StackLayout
Orientation="Horizontal"
HorizontalOptions="Center"
>
<Button
Text="確定"
Command="{Binding 客製化對話窗確定Command}"
/>
<Button
Text="取消"
Command="{Binding 客製化對話窗取消Command}"
/>
</StackLayout>
</StackLayout>
</Grid>
</ContentView>
- 在核心PCL專案的
UserControls
資料夾,開啟CustDialogUserControl.xaml.cs
檔案 - 將底下 C# 複製到剛剛開啟的檔案內
CustDialogUserControl.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace CustomDiag.UserControls
{
public partial class CustDialogUserControl : ContentView
{
public CustDialogUserControl()
{
InitializeComponent();
}
}
}
建立 ProcessingUserControl 使用者控制項 (User COntrol)
- 滑鼠右擊核心PCL專案的
UserControls
資料夾,選擇加入
>新增項目
- 在對話窗點選
Visual C#
>Cross-Platform
>Forms Xaml Page
- 在名稱欄位輸入
ProcessingUserControl
,接著點選新增
按鈕 - 將底下 XAML 標記宣告複製到剛剛建立的檔案內
ProcessingUserControl.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomDiag.UserControls.ProcessingUserControl">
<Grid
HorizontalOptions="Fill" VerticalOptions="Fill"
>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="150" />
</Grid.RowDefinitions>
<BoxView
Grid.Row="0" Grid.RowSpan="2"
BackgroundColor="#BB000000"
>
<BoxView.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding 點選遮罩Command}"
NumberOfTapsRequired="1" />
</BoxView.GestureRecognizers>
</BoxView>
<StackLayout
Grid.Row="0"
HorizontalOptions="Center" VerticalOptions="Center"
Margin="20,0"
>
<Label
Text="{Binding 處理中ViewModel.處理中訊息}"
TextColor="#FFFFFF"
FontSize="30"
HorizontalOptions="Center"
/>
<Label
Text="{Binding 處理中ViewModel.處理中狀態文字}"
TextColor="#FFFFFF"
Margin="0,30,0,0"
FontSize="20"
HorizontalOptions="Center"
/>
</StackLayout>
<ActivityIndicator
Grid.Row="1"
Color="#53ff1a"
WidthRequest="50" HeightRequest="50"
HorizontalOptions="Center" VerticalOptions="Center"
IsRunning="{Binding 處理中ViewModel.忙碌中控制項使用中}"
/>
</Grid>
</ContentView>
- 在核心PCL專案的
UserControls
資料夾,開啟ProcessingUserControl.xaml.cs
檔案 - 將底下 C# 複製到剛剛開啟的檔案內
ProcessingUserControl.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace CustomDiag.UserControls
{
public partial class ProcessingUserControl : ContentView
{
public ProcessingUserControl()
{
InitializeComponent();
}
}
}
修改 MainPage 檢視 (View)
- 在核心PCL專案的
Views
資料夾,滑鼠雙擊MainPage.xaml
- 將底下 XAML 複製到剛剛開啟的檔案內
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:UserControls="clr-namespace:CustomDiag.UserControls"
x:Class="CustomDiag.Views.MainPage"
BackgroundColor="#ffaa80"
Title="MainPage">
<Grid>
<StackLayout
Spacing="30"
HorizontalOptions="Center" VerticalOptions="Center">
<Button Text="客製化對話窗"
Command="{Binding 客製化對話窗Command}"
/>
<Label Text="{Binding 使用者輸入內容}"/>
<Button Text="處理中遮罩"
Command="{Binding 處理中遮罩Command}"/>
</StackLayout>
<UserControls:ProcessingUserControl
IsVisible="{Binding 處理中ViewModel.顯示處理中遮罩}"
/>
<UserControls:CustDialogUserControl
IsVisible="{Binding 客製化使用者對話窗ViewModel.顯示客製化使用者對話窗}"
/>
</Grid>
</ContentPage>
建立 CustDialogUserControlViewModel 檢視模型 (ViewModel)
- 滑鼠右擊核心PCL專案的
ViewModels
資料夾,選擇加入
>新增項目
- 在對話窗點選
Visual C#
>Prism
>Prism ViewModel
- 在名稱欄位輸入
CustDialogUserControlViewModel
,接著點選新增
按鈕 - 將底下 C# 程式碼複製到剛剛建立的檔案內
CustDialogUserControlViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
namespace CustomDiag.ViewModels
{
public class CustDialogUserControlViewModel : BindableBase
{
#region ViewModel
#region 顯示客製化使用者對話窗
private bool _顯示客製化使用者對話窗 = false;
public bool 顯示客製化使用者對話窗
{
get { return _顯示客製化使用者對話窗; }
set { SetProperty(ref _顯示客製化使用者對話窗, value); }
}
#endregion
#region 對話窗主題
private string _對話窗主題 = "";
public string 對話窗主題
{
get { return _對話窗主題; }
set { SetProperty(ref _對話窗主題, value); }
}
#endregion
#region 對話窗訊息
private string _對話窗訊息 = "";
public string 對話窗訊息
{
get { return _對話窗訊息; }
set { SetProperty(ref _對話窗訊息, value); }
}
#endregion
#region 對話窗使用者帳號
private string _對話窗使用者帳號 = "";
public string 對話窗使用者帳號
{
get { return _對話窗使用者帳號; }
set { SetProperty(ref _對話窗使用者帳號, value); }
}
#endregion
#region 對話窗使使用者密碼
private string _對話窗使使用者密碼 = "";
public string 對話窗使使用者密碼
{
get { return _對話窗使使用者密碼; }
set { SetProperty(ref _對話窗使使用者密碼, value); }
}
#endregion
#endregion
public CustDialogUserControlViewModel()
{
}
public void 顯示客製化使用者對話窗控制項(string p對話窗主題, string p對話窗訊息)
{
對話窗主題 = p對話窗主題;
對話窗訊息 = p對話窗訊息;
對話窗使用者帳號 = "";
對話窗使使用者密碼 = "";
顯示客製化使用者對話窗 = true;
}
public void 關閉客製化使用者對話窗控制項()
{
顯示客製化使用者對話窗 = false;
}
}
}
建立 ProcessingUserControlViewModel 檢視模型 (ViewModel)
- 滑鼠右擊核心PCL專案的
ViewModels
資料夾,選擇加入
>新增項目
- 在對話窗點選
Visual C#
>Prism
>Prism ViewModel
- 在名稱欄位輸入
ProcessingUserControlViewModel
,接著點選新增
按鈕 - 將底下 C# 程式碼複製到剛剛建立的檔案內
ProcessingUserControlViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
namespace CustomDiag.ViewModels
{
public class ProcessingUserControlViewModel : BindableBase
{
#region ViewModel
#region 顯示處理中遮罩
private bool _顯示處理中遮罩 = false;
public bool 顯示處理中遮罩
{
get { return _顯示處理中遮罩; }
set { SetProperty(ref _顯示處理中遮罩, value); }
}
#endregion
#region 忙碌中控制項使用中
private bool _忙碌中控制項使用中 = true;
public bool 忙碌中控制項使用中
{
get { return _忙碌中控制項使用中; }
set { SetProperty(ref _忙碌中控制項使用中, value); }
}
#endregion
#region 處理中訊息
private string _處理中訊息 = "";
public string 處理中訊息
{
get { return _處理中訊息; }
set { SetProperty(ref _處理中訊息, value); }
}
#endregion
#region 處理中狀態文字
private string _處理中狀態文字 = "";
public string 處理中狀態文字
{
get { return _處理中狀態文字; }
set { SetProperty(ref _處理中狀態文字, value); }
}
#endregion
#endregion
public ProcessingUserControlViewModel()
{
}
public void 顯示忙碌中使用者控制項(string p處理中訊息, string p處理中狀態文字)
{
處理中訊息 = p處理中訊息;
處理中狀態文字 = p處理中狀態文字;
顯示處理中遮罩 = true;
忙碌中控制項使用中 = true;
}
public void 關閉忙碌中使用者控制項()
{
處理中訊息 = "";
處理中狀態文字 = "";
顯示處理中遮罩 = false;
忙碌中控制項使用中 = false;
}
}
}
修改 MainPageViewModel 檢視模型 (ViewModel)
- 在核心PCL專案的
Views
資料夾,滑鼠雙擊MainPageViewModel.cs
- 將底下 XAML 複製到剛剛開啟的檔案內
MainPageViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CustomDiag.ViewModels
{
public class MainPageViewModel : BindableBase, INavigationAware
{
#region DI
INavigationService _navigationService;
IPageDialogService _dialogService;
#endregion
#region ICommand
public DelegateCommand 客製化對話窗Command { get; set; }
public DelegateCommand 處理中遮罩Command { get; set; }
public DelegateCommand 點選遮罩Command { get; set; }
public DelegateCommand 客製化對話窗確定Command { get; set; }
public DelegateCommand 客製化對話窗取消Command { get; set; }
#endregion
#region ViewModel
#region 顯示客製化對話窗
private bool _顯示客製化對話窗 = false;
public bool 顯示客製化對話窗
{
get { return _顯示客製化對話窗; }
set { SetProperty(ref _顯示客製化對話窗, value); }
}
#endregion
#region 對話窗主題
private string _對話窗主題 = "";
public string 對話窗主題
{
get { return _對話窗主題; }
set { SetProperty(ref _對話窗主題, value); }
}
#endregion
#region 對話窗內容
private string _對話窗內容 = "";
public string 對話窗內容
{
get { return _對話窗內容; }
set { SetProperty(ref _對話窗內容, value); }
}
#endregion
#region 使用者輸入內容
private string _使用者輸入內容 = "";
public string 使用者輸入內容
{
get { return _使用者輸入內容; }
set { SetProperty(ref _使用者輸入內容, value); }
}
#endregion
public ProcessingUserControlViewModel 處理中ViewModel { get; set; } = new ProcessingUserControlViewModel();
public CustDialogUserControlViewModel 客製化使用者對話窗ViewModel { get; set; } = new CustDialogUserControlViewModel();
#endregion
public MainPageViewModel(INavigationService navigationService, IPageDialogService dialogService)
{
_navigationService = navigationService;
_dialogService = dialogService;
客製化對話窗Command = new DelegateCommand(客製化對話窗);
處理中遮罩Command = new DelegateCommand(處理中遮罩);
點選遮罩Command = new DelegateCommand(點選遮罩);
客製化對話窗確定Command = new DelegateCommand(客製化對話窗確定);
客製化對話窗取消Command = new DelegateCommand(客製化對話窗取消);
}
private void 客製化對話窗取消()
{
使用者輸入內容 = "";
客製化使用者對話窗ViewModel.關閉客製化使用者對話窗控制項();
}
private async void 客製化對話窗確定()
{
if (string.IsNullOrEmpty(客製化使用者對話窗ViewModel.對話窗使用者帳號) || 客製化使用者對話窗ViewModel.對話窗使用者帳號.Length < 6)
{
await _dialogService.DisplayAlertAsync("警告", "帳號不可為空值或者小於6個字元", "確定");
}
else if (string.IsNullOrEmpty(客製化使用者對話窗ViewModel.對話窗使使用者密碼) || 客製化使用者對話窗ViewModel.對話窗使使用者密碼.Length < 8)
{
await _dialogService.DisplayAlertAsync("警告", "密碼不可為空值或者小於8個字元", "確定");
}
else
{
使用者輸入內容 = $"帳號:{客製化使用者對話窗ViewModel.對話窗使用者帳號} / 密碼: {客製化使用者對話窗ViewModel.對話窗使使用者密碼}";
客製化使用者對話窗ViewModel.關閉客製化使用者對話窗控制項();
}
}
private void 點選遮罩()
{
處理中ViewModel.關閉忙碌中使用者控制項();
}
private async void 處理中遮罩()
{
處理中ViewModel.顯示忙碌中使用者控制項("正在更新資料", "正在更新資料,需要2秒鐘");
await Task.Delay(2000);
處理中ViewModel.關閉忙碌中使用者控制項();
}
private void 客製化對話窗()
{
客製化使用者對話窗ViewModel.顯示客製化使用者對話窗控制項("請進行身分驗證", "請輸入您的帳號與密碼,並且點選確定按鈕");
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatedTo(NavigationParameters parameters)
{
}
}
}
DisplayAlert
與DisplayActionSheet
,而在 Prism 開發框架之下,也可以使用建構式注入IPageDialogService
介面,透過其注入的執行個體,使用DisplayAlertAsync
與DisplayActionSheetAsync
,來與使用者進行互動。很多時候,您也希望能夠告知應用程式操作的使用者,現在應用程式正在忙碌執行中,並且顯示出相關訊息,讓使用者知道現在處理請況;或者,需要能夠顯示一個客製的對話窗,讓使用者輸入或者填寫相關訊息,而不需要做頁面切換。