XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書
顯示具有 C# 標籤的文章。 顯示所有文章
顯示具有 C# 標籤的文章。 顯示所有文章

2016/09/16

Xamarin.Forms 自訂附加屬性 Attached Property

在這個範例中,將會說明如何產生一個具有類似 Grid.Row 這樣用法的附加屬性;這裡,將會新建一個附加屬性類別,當這個附加屬性設定在 Entry 控制項上的時候,就會自動設定該 Entry 控制項上的其他相關屬性。
自訂附加屬性
首先您需要先產生一個類別。
使用 BindableProperty.CreateAttached 靜態方法,產生一個附加屬性物件,在產生這個附加屬性的當時,定義 propertyChanged 引數,用於設定當該附加屬性值有異動的時候,需要呼叫的委派方法;在這個方法內,將會依據新設定的附加屬性值,設定所附加這個 Entry 的浮水印、字體大小、輸入鍵盤的屬性;若附加屬性並不是設定 Entry 控制項內,則不會做任何處理動作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace AttProp
{
    public class EntryTypeAttached
    {
        public static readonly BindableProperty EntryTypeProperty =
               BindableProperty.CreateAttached(
                   propertyName: "EntryType",
                   returnType: typeof(string),
                   declaringType: typeof(Entry),
                   defaultValue: null,
                   defaultBindingMode: BindingMode.OneWay,
                   validateValue: null,
                   propertyChanged: OnEntryTypeChanged);

        private static void OnEntryTypeChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var fooEntry = bindable as Entry;
            if (fooEntry == null)
                return;

            var foooldValue = (oldValue as string)?.ToLower();
            var foonewValue = (newValue as string)?.ToLower();
            if(foonewValue == null)
            {
                return;
            }
            switch (foonewValue)
            {
                case "None":
                    break;
                case "email":
                    fooEntry.SetValue(Entry.PlaceholderProperty, "請輸入電子郵件");
                    fooEntry.Keyboard = Keyboard.Email;
                    fooEntry.FontSize = 20;
                    break;
                case "phone":
                    fooEntry.SetValue(Entry.PlaceholderProperty, "請輸入電話號碼");
                    fooEntry.Keyboard = Keyboard.Telephone;
                    fooEntry.FontSize = 20;
                    break;
                case "number":
                    fooEntry.SetValue(Entry.PlaceholderProperty, "請輸入數值");
                    fooEntry.Keyboard = Keyboard.Numeric;
                    fooEntry.FontSize = 20;
                    break;
                default:
                    break;
            }
        }

        // Helper methods for attached bindable property. 
        public static void SetEntryType(BindableObject bindable, string entryType)
        {
            bindable.SetValue(EntryTypeProperty, entryType);
        }
        public static string GetEntryType(BindableObject bindable)
        {
            return (string)bindable.GetValue(EntryTypeProperty);
        }
    }
}
當要引用這個附加屬性到 Entry 控制項內,可參考底下用法:
在這裡,您需要先定義使用這個附加屬性的 XAML 命名空間,您可以在根項目內,使用xmlns:CustomAttached="clr-namespace:AttProp"來加入新可使用的 XAML 命名空間。
此時,您就可以在 XAML 頁面中,在 Entry 控制項內,使用這個新建立的附加屬性 : <EntryCustomAttached:EntryTypeAttached.EntryType="Email" />
<?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:CustomAttached="clr-namespace:AttProp"
             x:Class="AttProp.Views.MainPage"
             Title="MainPage">
  <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
    <Label Text="自訂附加屬性 Attached Property" />
    <Entry />
    <Entry CustomAttached:EntryTypeAttached.EntryType="Email" />
    <Entry CustomAttached:EntryTypeAttached.EntryType="Phone" />
    <Entry CustomAttached:EntryTypeAttached.EntryType="Number" />
  </StackLayout>
</ContentPage>

2016/09/15

Xamarin.Forms Image 圖片控制項的特色與使用說明

這份筆記將會描述 Xamarin.Forms 內的 XAML Image 控制項的各項使用方式與其相關屬性設定方式。
在 Image 控制項,其圖片來源是透過 Source 屬性來設定,基本上,您可以使用文字來說明這個圖片是從網路上而得到,或者這個圖片是位於每個專屬專案內。若您想要從核心PCL專案內或者從您應用程式檔案系統內取得,則需要搭配其他方式來做到。
當然,上述的各種不同圖片來源各有不同的效果,原則上,若是採用後兩者(PCL / 本機檔案系統),則這些圖片是可以在不同平台上進行共用的;底下將會進行說明。
這份筆記的範例專案可以從底下取得

圖片來源

c sharp 的用法

圖片資源可以透過 ImageSource 類別提供的四個靜態方法來取得圖片
  • ImageSource.FromFile
    這個方法可以取得個專屬平台下的圖片檔案
  • ImageSource.FromUri
    這個方法是透過一個網址,取得網路上的圖片資源
  • ImageSource.FromeResource
    這個方法可以讓您取得核心PCL專案內的圖片檔案
  • ImageSource.FromStream
    這個方法可以讓您取得本機應用程式下載後的圖片檔案

XAML 的用法

  • 取得個專屬平台下的圖片檔案
    在 Source 屬性內,直接定義一個在專屬平台內的圖片檔案名稱,就可以從每個專屬專案平台下取得這個圖片檔案;若每個專案平台的圖片檔案路徑或者檔案名稱不同,可以使用 OnPlatform 來指定不同平台下的實際圖片檔案名稱與路徑。
<Image Grid.Row="1" Grid.Column="0" Source="platformImage.jpg" />
  • 取得網路上的圖片資源
    在 Source 屬性內,可以使用一個網址字串,就會讓 Image 自動從網路下載這個圖片
<Image Source="https://developer.xamarin.com/demo/IMG_3256.JPG?width=640" />
  • 取得核心PCL專案內的圖片檔案
    若想要在取得 PCL 專案內的圖片檔案,您需要客製化一個有建置 IMarkupExtension 介面的類別,並且在 XAML 內提供取得 PCL 內的圖片檔案。
<Image Grid.Row="0" Grid.Column="1" Source="{extMark:ImageResource XFImage.Assets.platformImage.jpg}"/>
該 IMarkupExtension 的類別的程式碼,如下所示,在 ImageResourceExtension 類別中,使用了ImageSource.FromResource 取出 PCL 內的圖片檔案並且轉換成為 ImageSource
    public class ImageResourceExtension : IMarkupExtension
    {
        public string Source { get; set; }
        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Source == null) return null;
            return ImageSource.FromResource(Source);
        }
    }
  • 取得本機應用程式下載後的圖片檔案
    這裡有兩種方法,一個是在 ViewModel 定義一個 ImageSource 的可綁定屬性,透過 ViewModel 內的方法,取得本機檔案的圖片檔案;在這裡,使用了 PCL Storage 這個套件,讓您可以在 PCL 專案內,取得本機檔案。
 <Image Grid.Row="1" Grid.Column="1" Source="{Binding MyImageSource}" />
ViewModel 內的可綁定 ImageSource 屬性
        private ImageSource myImageSource;
        public ImageSource MyImageSource
        {
            get { return myImageSource; }
            set { SetProperty(ref myImageSource, value); }
        }
底下的為在 ViewModel 內的某個 RelayCommand 方法,當按下這個按鈕,就會使用 HttpClient 物件來下載網路上的圖片,並且使用 PCL Storage 將這個圖片檔案儲存到本機上。
接著,使用 ImageSource.FromStream(() => fooTargetReadStream) 方法,取得這個圖片檔案的 ImageSource 物件,以便可以顯示在頁面上。
            #region 從網路下載後,先儲存到本機檔案系統內,接著再讀出來,進行圖片資料綁定
            HttpClient client = new HttpClient();
            IFolder rootFolder = FileSystem.Current.LocalStorage;
            IFolder folder = await rootFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists);
            IFile file = await folder.CreateFileAsync("MyLocalImage.jpg", CreationCollisionOption.ReplaceExisting);
            using (var fooTargetStream = await file.OpenAsync(FileAccess.ReadAndWrite))
            {
                using (var fooSourceString = await client.GetStreamAsync("https://developer.xamarin.com/demo/IMG_3256.JPG?width=640"))
                {
                    await fooSourceString.CopyToAsync(fooTargetStream);
                }
            }

            file = await folder.GetFileAsync("MyLocalImage.jpg");
            var fooTargetReadStream = await file.OpenAsync(FileAccess.Read);
            MyImageSource = ImageSource.FromStream(() => fooTargetReadStream);
            #endregion
另外一個方法就是使用數值轉換器 Value Converter,使用這個解決方案,您需要定義一個新類別,且建置IValueConverter 介面,如下所示:
這段數值轉換器使用了 PCL Storage 套件,取得該該圖片檔案的內容,接著透過 ImageSource.FromStream靜態方法取得 ImageSource 物件。
    class StringToLocalImage : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string foo1 = value as string;
            ImageSource fooImageSource=null;

            if (string.IsNullOrEmpty(foo1) == false)
            {
                IFolder rootFolder = FileSystem.Current.LocalStorage;
                IFolder folder;
                IFile file;
                folder = rootFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists).Result;
                file = folder.GetFileAsync(foo1).Result;
                var fooStream = file.OpenAsync(FileAccess.Read).Result;
                Debug.WriteLine($"Length: {fooStream.Length}");

                fooImageSource = ImageSource.FromStream(() => fooStream);
            }
            else
            {
            }

            //fooImageSource= ImageSource.FromUri(new Uri("https://developer.xamarin.com/demo/IMG_1415.JPG?height=640"));

            return fooImageSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
在 XAML 下,可以使用這樣的方式來宣告
    <Image Grid.Row="2" Grid.Column="1"
          Source="{Binding LocalImage2, Converter={StaticResource StringToLocalImage}}" />

Aspect

這個屬性是用來控制圖片要顯示何種大小,這裡需要使用 Aspect 的屬性。
  • Fill
    會自動將圖片充滿整個容器內,這可能會導致圖片會失真。
  • AspectFill
    使用等比例的放大,讓圖片不會失真,但是,會導致有些圖片區域無法顯示出來。
  • AspectFit
    使用等比例的放大,讓圖片不會失真,但是,會導致有些區域留下空白的內容。

2016/09/12

Xamarin.Forms 使用者自訂對話窗與PopUp應用 頁面

使用者自訂對話窗與PopUp應用 頁面

目的

當在進行 Xamarin.Forms 專案開發的時候,除了 Xamarin.Forms 基本提供的 DisplayAlert 與DisplayActionSheet,而在 Prism 開發框架之下,也可以使用建構式注入 IPageDialogService 介面,透過其注入的執行個體,使用 DisplayAlertAsync 與 DisplayActionSheetAsync,來與使用者進行互動。很多時候,您也希望能夠告知應用程式操作的使用者,現在應用程式正在忙碌執行中,並且顯示出相關訊息,讓使用者知道現在處理請況;或者,需要能夠顯示一個客製的對話窗,讓使用者輸入或者填寫相關訊息,而不需要做頁面切換。
在這篇文章中,將會說明如何客製一個使用者對話窗,並且產生一個頁面遮罩,讓這個對話窗顯示在原來頁面之上。
對話窗與動作選項

學習重點

在這個練習專案中,將會讓您學會底下技能與方法的使用:
  • 使用 ContentView 產生許多使用者控制項 (User Control),可以反覆使用的控制項
  • 如何在相關頁面之中,引用這些新建立的使用者控制項
  • 使用檢視模型 (ViewModel) 來控制使用者控制項顯示與否和進行資料繫結
  • 如何處理與回應使用者控制項中的相關事件或者 ICommand
  • 使用顏色來表示螢幕遮罩的方法
  • 讀取使用者控制項所輸入或者回應的資料和訊息
  • 在 XAML 內,使用手勢操作(GestureRecognizers)判斷使用者點選使用者控制項,以便中止顯示該控制項

專案原始碼

專案使用到的圖片

實作方法

建立專案

  1. 在 Visual Studio 2015,點選功能表 檔案 > 新增 > 專案
  2. 在 新增專案 對話窗內,點選 範本 > Visual C# > Prism > Prism Unity App (Forms)
  3. 在底下名稱欄位中,輸入 CustomDiag 最後,點選 確定 按鈕。
  4. 當出現 Prism for Xamarin.Forms - Project Wizard 對話窗,請勾選 AndroidiOSUWP 這三個選項,表示您想要產生使用 Prism 框架的這三種原生 Xamarin.Forms 專案,最後點選 Create 按鈕。
當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到 Xamarin Mac Agent Instructions 對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。
  1. 接著會看到 新的通用Windows專案 對話視窗,此時,您只需要按下 確定 按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。
  2. 最後,整個新的 Xamarin.Forms 專案就建立完成了。
若您無法看到 Prism 項目,用來建立 Prism 類型專案,那可能是您的 Visual Studio 2015 內沒有安裝Prism Template Pack 擴充功能,請參考 附件 : 使用 Visual Studio 2015 增加 Prism 專案樣版
  1. 滑鼠右擊 CustomDiag.Droid,選擇 設定為起始專案
  2. 展開 CustomDiag.Droid > Properties,滑鼠雙擊 Properties 這個節點
  3. 在標籤頁次 Application,選擇項目 Minimum Android to target的下拉選單,選擇值為 Android 4.4 (API Level 19 - Kit Kat) 這個選項,接著按下 Ctrl + S 組合案件,儲存此次修改設定。
  4. 滑鼠右擊 CustomDiag.Droid,選擇 建置 進行專案編譯

開發前準備工作

建立資料夾

  1. 請在核心PCL 專案內,建立一個 UserControls 資料夾

複製專案使用的圖片檔案

專案開發

建立 CustDialogUserControl 使用者控制項 (User COntrol)

  1. 滑鼠右擊核心PCL專案的 UserControls 資料夾,選擇 加入 > 新增項目
  2. 在對話窗點選 Visual C# > Cross-Platform > Forms Xaml Page
  3. 在名稱欄位輸入 CustDialogUserControl,接著點選 新增 按鈕
  4. 將底下 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>
  1. 在核心PCL專案的 UserControls 資料夾,開啟 CustDialogUserControl.xaml.cs 檔案
  2. 將底下 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)

  1. 滑鼠右擊核心PCL專案的 UserControls 資料夾,選擇 加入 > 新增項目
  2. 在對話窗點選 Visual C# > Cross-Platform > Forms Xaml Page
  3. 在名稱欄位輸入 ProcessingUserControl,接著點選 新增 按鈕
  4. 將底下 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>
  1. 在核心PCL專案的 UserControls 資料夾,開啟 ProcessingUserControl.xaml.cs 檔案
  2. 將底下 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)

  1. 在核心PCL專案的 Views 資料夾,滑鼠雙擊 MainPage.xaml
  2. 將底下 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)

  1. 滑鼠右擊核心PCL專案的 ViewModels 資料夾,選擇 加入 > 新增項目
  2. 在對話窗點選 Visual C# > Prism > Prism ViewModel
  3. 在名稱欄位輸入 CustDialogUserControlViewModel,接著點選 新增 按鈕
  4. 將底下 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)

  1. 滑鼠右擊核心PCL專案的 ViewModels 資料夾,選擇 加入 > 新增項目
  2. 在對話窗點選 Visual C# > Prism > Prism ViewModel
  3. 在名稱欄位輸入 ProcessingUserControlViewModel,接著點選 新增 按鈕
  4. 將底下 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)

  1. 在核心PCL專案的 Views 資料夾,滑鼠雙擊 MainPageViewModel.cs
  2. 將底下 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)
        {
        }
    }
}