XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2016/10/23

Xamarin.Forms 開放資料跨平台應用程式開發 顯示清單項目明細

在上一個練習中,您已經可以透過網路取得創業空間的相關資料,並且顯示到螢幕上,接下來,在這個練習中,您將須要讓使用者在點選創業空間清單項目的時候,可以取得使用者是點選哪個項目,並且導航到另外一個頁面,將所選擇的資料明細顯示出來。
在這個階段的練習,您將會學會底下的 Xamarin.Forms 的開發技術:
  1. 建立創業空間項目的詳細頁面檢視與檢視模型
  2. 建立可以顯示 HTML 內容的頁面檢視與檢視模型
  3. 註冊此次新加入的 View
  4. 使用 XAML (行為)Behavior 與命令 (ICommand)
  5. 產生將文字內容軟換成為 HtmlWebViewSource 的數值轉換器 (Value Converter)
  6. 設定 XAML 全域資源

建立創業空間明細模型

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 ViewModels 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 創業空間明細ViewModel,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

創業空間明細ViewModel.cs

  1. 這個類別 創業空間明細 將會用來定義在顯示在資料明細頁面上的檢視模型。
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFCreative.ViewModels
{
    public class 創業空間明細 : BindableBase
    {
        #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

        #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

        #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

        #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 聯絡email
        private string _聯絡email;

        public string 聯絡email
        {
            get { return _聯絡email; }
            set { SetProperty(ref _聯絡email, 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

        #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

        #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 DateTime _建立時間;

        public DateTime 建立時間
        {
            get { return _建立時間; }
            set { SetProperty(ref _建立時間, value); }
        }
        #endregion

        #region 修改時間
        private DateTime _修改時間;

        public DateTime 修改時間
        {
            get { return _修改時間; }
            set { SetProperty(ref _修改時間, value); }
        }
        #endregion

    }
}

建立創業空間項目的詳細頁面檢視與檢視模型

創業空間項目的詳細頁面 View

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 Views 資料夾,接著,選擇 加入 > 新增項目
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > Prism > Prism ContentPage (Forms)
  3. 在底下名稱欄位內,輸入 BusinessSpaceDetailPage,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

BusinessSpaceDetailPage.xaml

  1. 在這裡的根項目 (Root Element) 使用的是 ContentPage
  2. 在這個頁面內,有兩個 Button 項目(Element),不過,在這裡並不使用 Code Behind 的方式來定義這兩個按鈕的相對應是件,而是透過,Command 屬性,將檢視模型內的 ICommand 物件,透過資料繫結方式綁定在一起;也就是說,當使用者按下這個按鈕,這個 ICommand 委派的方法就會在檢視模型內運行。透過這樣的設計,您就不再需要 Code Behind 機制,所有的商業處理邏輯,都可以在檢視模型內設計了。
<?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"
  x:Class="XFCreative.Views.BusinessSpaceDetailPage"
  Title="創業空間明細">

  <ContentPage.Resources>
    <ResourceDictionary>
      <OnPlatform
        x:Key="標題大小" x:TypeArguments="x:Double"
        iOS="18" Android="18" WinPhone="18" />
      <x:Double x:Key="標題大小1">18</x:Double>
      <Thickness x:Key="項目距離">0,20,0,0</Thickness>
    </ResourceDictionary>
  </ContentPage.Resources>

  <ScrollView
    Orientation="Vertical"
    >
    <StackLayout
      Orientation="Vertical"
      Margin="20,0"
      >
      <Image
        Margin="0,20,0,20"
        >
        <Image.Source>
          <OnPlatform x:TypeArguments="ImageSource"
            iOS="info.png"
            Android="info.png"
            WinPhone="refresh/info.png" />
        </Image.Source>

      </Image>
      <Label
        Text="創業空間名稱"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"/>
      <Label
        Text="{Binding 創業空間明細.創業空間名稱}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="所屬單位"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.所屬單位}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="創業空間類型"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.創業空間類型}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="招募團隊類型"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.招募團隊類型}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="座標經緯度"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.座標經度, StringFormat='經度: {0}'}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />
      <Label
        Text="{Binding 創業空間明細.座標緯度, StringFormat='緯度: {0}'}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="空間是否出租"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.空間是否出租}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="空間主照片"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Image
        Source="{Binding 創業空間明細.空間主照片}"
        Aspect="AspectFit"
        VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
        />

      <Label
        Text="縣市區域"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.縣市區域}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="地址"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.地址}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="標籤"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.標籤}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="詳細照片"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Image
        Source="{Binding 創業空間明細.詳細照片}"
        Aspect="AspectFit"
        VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
        />

      <Label
        Text="聯絡人"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.聯絡人}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="連絡電話"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.連絡電話}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="聯絡email"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.聯絡email}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="官方網站"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.官方網站}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="建築類型"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.建築類型}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="建造材質"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.建造材質}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="建物現況"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.建物現況}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="樓別樓高"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.樓別樓高}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="使用坪數"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.使用坪數}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="空間資訊"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Button Text="查看 空間資訊" Command="{Binding 查看空間資訊Command}" />

      <Label
        Text="進駐使用人數"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.進駐使用人數}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="價格方案"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Button Text="查看 價格方案" Command="{Binding 查看價格方案Command}" />

      <Label
        Text="使用時間"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.使用時間}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="備註"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.備註}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="建立時間"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.建立時間}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

      <Label
        Text="修改時間"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <Label
        Text="{Binding 創業空間明細.修改時間}"
        VerticalOptions="Center" HorizontalOptions="Start"
        />

    </StackLayout>
  </ScrollView>
</ContentPage>

創業空間項目的詳細頁面 ViewModel

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 ViewModels 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 BusinessSpaceDetailPageViewModel,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

BusinessSpaceDetailPageViewModel.cs

  1. 在 BusinessSpaceDetailPageViewModel 類別內,透過 OnNavigatedTo 事件方法取得了要顯示資料的參數,您可以透過 NavigationParameters 資料字典取得所傳遞進來的資料,並且透過 系統初始化 方法,把要顯示的資料產生在相對應的檢視模型物件內。
  2. 在建構式內,使用 DelegateCommand 產生了兩個 DelegateCommand 的委派方法,這兩個方法會當使用者按下畫面中的按鈕,就會來執行相對應的方法。
  3. 查看空間資訊() 與 查看價格方案() 方法內,展示了如何導航到另外一個頁面,並且如何傳遞參數到新的頁面。這裡是透過了產生 NavigationParameters 類別,將要傳遞過去的參數,使用資料字典的方式存放在這個物件之內,並且使用 await _navigationService.Navigate 方法,把這個要傳遞過去的參數傳送到新頁面。
using Newtonsoft.Json;
using Plugin.ExternalMaps;
using Plugin.Messaging;
using Plugin.Share;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using XFCreative.Models;
using XFCreative.Services;

namespace XFCreative.ViewModels
{
    public class BusinessSpaceDetailPageViewModel : BindableBase, INavigationAware
    {
        private readonly INavigationService _navigationService;

        public DelegateCommand 查看空間資訊Command { get; set; }
        public DelegateCommand 查看價格方案Command { get; set; }

        private 創業空間明細 _創業空間明細;
        public 創業空間明細 創業空間明細
        {
            get { return _創業空間明細; }
            set { SetProperty(ref _創業空間明細, value); }
        }
        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public BusinessSpaceDetailPageViewModel(INavigationService navigationService)
        {
            // 取得頁面導航的實作
            _navigationService = navigationService;

            查看空間資訊Command = new DelegateCommand(查看空間資訊);
            查看價格方案Command = new DelegateCommand(查看價格方案);
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("創業空間Selected"))
            {
                var foo創業空間Selected = parameters["創業空間Selected"] as 創業空間NodeViewModel;
                系統初始化(foo創業空間Selected);
            }

        }

        public void 系統初始化(創業空間NodeViewModel 創業空間NodeViewModel)
        {
            var fooItem = GlobalData.創業空間Repository.Items.FirstOrDefault(x => x.創業空間名稱 == 創業空間NodeViewModel.創業空間名稱);
            if (fooItem != null)
            {
                創業空間明細 = new 創業空間明細()
                {
                    創業空間名稱 = fooItem.創業空間名稱,
                    使用坪數 = fooItem.使用坪數,
                    使用時間 = fooItem.使用時間,
                    修改時間 = fooItem.修改時間,
                    備註 = fooItem.備註,
                    價格方案 = fooItem.價格方案,
                    創業空間類型 = fooItem.創業空間類型,
                    地址 = fooItem.地址,
                    官方網站 = fooItem.官方網站,
                    座標經度 = fooItem.座標經度,
                    座標緯度 = fooItem.座標緯度,
                    建物現況 = fooItem.建物現況,
                    建立時間 = fooItem.建立時間,
                    建築類型 = fooItem.建築類型,
                    建造材質 = fooItem.建造材質,
                    所屬單位 = fooItem.所屬單位,
                    招募團隊類型 = fooItem.招募團隊類型,
                    樓別樓高 = fooItem.樓別樓高,
                    標籤 = fooItem.標籤,
                    空間主照片 = fooItem.空間主照片,
                    空間是否出租 = fooItem.空間是否出租,
                    空間資訊 = fooItem.空間資訊,
                    縣市區域 = fooItem.縣市區域,
                    聯絡email = fooItem.聯絡email,
                    聯絡人 = fooItem.聯絡人,
                    詳細照片 = fooItem.詳細照片,
                    連絡電話 = fooItem.連絡電話,
                    進駐使用人數 = fooItem.進駐使用人數,
                };
            }
        }

        private async void 查看空間資訊()
        {
            var fooNavigationParameters = new NavigationParameters();
            var fooItem = new 網頁資料NodeViewModel()
            {
                標題名稱 = "空間資訊",
                網頁內容 = 創業空間明細.空間資訊,
            };

            fooNavigationParameters.Add("網頁資料NodeViewModel", fooItem);
            await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
        }

        private async void 查看價格方案()
        {
            var fooNavigationParameters = new NavigationParameters();
            var fooItem = new 網頁資料NodeViewModel()
            {
                標題名稱 = "價格方案",
                網頁內容 = 創業空間明細.價格方案,
            };

            fooNavigationParameters.Add("網頁資料NodeViewModel", fooItem);
            await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
        }

    }
}

建立網頁資料 檢視模型

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 ViewModels 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 網頁資料NodeViewModel,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

網頁資料NodeViewModel.cs

  1. 這個類別 網頁資料NodeViewModel 將會用來使用 WebView 控制項目,來顯示這些 HTML 內容的檢視模型。
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFCreative.ViewModels
{
    public class 網頁資料NodeViewModel : BindableBase
    {
        #region 標題名稱
        private string _標題名稱;
        public string 標題名稱
        {
            get { return _標題名稱; }
            set { SetProperty(ref _標題名稱, value); }
        }
        #endregion

        #region 網頁內容
        private string _網頁內容;

        public string 網頁內容
        {
            get { return _網頁內容; }
            set { SetProperty(ref _網頁內容, value); }
        }
        #endregion

    }
}

建立可以顯示 HTML 內容的頁面檢視與檢視模型

可以顯示 HTML 內容的頁面 View

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 Views 資料夾,接著,選擇 加入 > 新增項目
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > Prism > Prism ContentPage (Forms)
  3. 在底下名稱欄位內,輸入 WebView更多資訊Page,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

WebView更多資訊Page.xaml

  1. 在這裡的根項目 (Root Element) 使用的是 ContentPage
  2. 這個頁面由 StackLayout 版面控制項目來進行配置 Label & WebView 這兩個控制項要顯示與排列方向
  3. WebView 控制項將會把 HTML 文字內容,實際呈現出來,在這裡,要顯示的 HTML 內容,將會透過資料繫結功能,把 WebView.Source 屬性欄位與 網頁資料NodeViewModel.網頁內容 檢視模型屬性綁定在一起。
<?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"
  Title="更多資訊"
  x:Class="XFCreative.Views.WebView更多資訊Page">

  <ContentPage.Resources>
    <ResourceDictionary>
      <OnPlatform
        x:Key="標題大小" x:TypeArguments="x:Double"
        iOS="18" Android="18" WinPhone="18" />
      <x:Double x:Key="標題大小1">18</x:Double>
      <Thickness x:Key="項目距離">0,20,0,0</Thickness>
    </ResourceDictionary>
  </ContentPage.Resources>

    <StackLayout
      VerticalOptions="Fill" HorizontalOptions="Fill"
      Orientation="Vertical"
    >
      <Label
        Text="{Binding 網頁資料NodeViewModel.標題名稱}"
        VerticalOptions="Center" HorizontalOptions="Start"
        FontSize="{Binding Source={StaticResource 標題大小}}"
        Margin="{Binding Source={StaticResource 項目距離}}"
        />
      <WebView
        Source="{Binding 網頁資料NodeViewModel.網頁內容, Converter={StaticResource StringToHtmlConverter}}"
        VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
        />
    </StackLayout>

</ContentPage>

可以顯示 HTML 內容的頁面 ViewModel

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 ViewModels 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 WebView更多資訊PageViewModel,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

WebView更多資訊PageViewModel.cs

  1. 在 WebView更多資訊PageViewModel 類別內,會在事件 OnNavigatedTo 取得要顯示的資料項目的參數內容,並且將要顯示的資料物件,設定到該檢視模型內的 NodeViewModel 物件。
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFCreative.ViewModels
{
    public class WebView更多資訊PageViewModel : BindableBase, INavigationAware
    {
        private readonly INavigationService _navigationService;

        private 網頁資料NodeViewModel _網頁資料NodeViewModel;
        public 網頁資料NodeViewModel 網頁資料NodeViewModel
        {
            get { return _網頁資料NodeViewModel; }
            set { SetProperty(ref _網頁資料NodeViewModel, value); }
        }

        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public WebView更多資訊PageViewModel(INavigationService navigationService)
        {
            // 取得頁面導航的實作
            _navigationService = navigationService;
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("網頁資料NodeViewModel"))
            {
                網頁資料NodeViewModel = parameters["網頁資料NodeViewModel"] as 網頁資料NodeViewModel;
            }
        }
    }
}

註冊此次新加入的 View

  1. 在核心PCL XFCreative 專案內,開啟 App.xaml.cs 檔案
  2. 使用底下程式碼替換掉剛剛開啟的檔案內容

App.xaml.cs

  1. 若您沒有進行底下程式碼的修正,若開始執行該專案,就會產生錯誤訊息:System.InvalidOperationException: HomePage could not be created. Please make sure you have registered HomePage for navigation.
  2. 在 App 類別的 RegisterTypes 方法中,您需要把 HomePage 與 BusinessSpacePage 這兩個檢視 (View) 註冊到 Unity 的容器內,這樣,當要導航到這些頁面的時候,Unity 容器將會自動解析出所要導航的頁面物件,並且自動進行相對應的檢視模型(ViewModel)的繫結與綁定動作。
  3. 另外,在建構式內,當要切換到頁面 MainPage 的命令中,將透過 title 參數,把要顯示的訊息傳遞到這個頁面內,這樣,系統就會顯示出這段文字。
using Prism.Unity;
using XFCreative.Views;

namespace XFCreative
{
    public partial class App : PrismApplication
    {
        protected override void OnInitialized()
        {
            InitializeComponent();

            NavigationService.Navigate("MainPage?title=請稍後,正在更新資料");
        }

        protected override void RegisterTypes()
        {
            Container.RegisterTypeForNavigation<MainPage>();
            Container.RegisterTypeForNavigation<HomePage>();
            Container.RegisterTypeForNavigation<BusinessSpacePage>();
        }
    }
}

使用 XAML (行為)Behavior 與命令 (ICommand)

檢視部分

您已經將要顯示的明細資料與可以顯示 HTML 內的頁面都寫好了,最後,就是要修改之前寫好的清單頁面,讓使用者在點選清單之後,可以將頁面切換到剛剛產生好的頁面。
  1. 在核心PCL XFCreative 專案內,開啟 Views 資料夾內的 BusinessSpacePage.xaml 檔案。
  2. 請在 <ListView.ItemTemplate> 上方,加入底下程式碼
    由於現在的 ListView 控制項,尚未針對點選某個項目提供相對應的 Command 屬性,因此,在這裡將會透過 XAML 行為 (Behavior) 來進行擴充。在這裡使用了 ListView.Behaviors 設定了當發生了ItemTapped 事件,就執行指定的 behaviors:InvokeCommandAction 的 ICommand 指定方法;這樣,您就可以在檢視模型內,定義一個 DelegateCommand 物件,醬可以透過資料繫結方式,綁定到檢視上了。
      <ListView.Behaviors>
        <behaviors:EventHandlerBehavior EventName="ItemTapped">
          <behaviors:InvokeCommandAction Command="{Binding 創業空間ItemSelectedCommand}"  />
        </behaviors:EventHandlerBehavior>
      </ListView.Behaviors>
  1. 使用底下完整程式碼替換掉剛剛開啟的檔案內容

BusinessSpacePage.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"
  xmlns:behaviors="clr-namespace:Behaviors;assembly=Behaviors"
  prism:ViewModelLocator.AutowireViewModel="True"
  x:Class="XFCreative.Views.BusinessSpacePage"
  Title="創業空間清單"
  >

  <Grid
    >
    <ListView
      x:Name="listview創業空間"
      ItemsSource="{Binding 創業空間Nodes, Mode=TwoWay}"
      SelectedItem="{Binding 創業空間Selected, Mode=TwoWay}"
      CachingStrategy="RecycleElement"
      RowHeight="100"
      >
      <ListView.Behaviors>
        <behaviors:EventHandlerBehavior EventName="ItemTapped">
          <behaviors:InvokeCommandAction Command="{Binding 創業空間ItemSelectedCommand}"  />
        </behaviors:EventHandlerBehavior>
      </ListView.Behaviors>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <Grid
                VerticalOptions="Center"
                  >
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="100" />
                  <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                  <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Label
                  Text ="{Binding 縣市區域}"
                  Margin="0,0,0,0"
                  FontSize="36"
                  HorizontalOptions="Start" VerticalOptions="Start"
                  HorizontalTextAlignment="Center"
                  LineBreakMode="WordWrap"
                    />

                <StackLayout
                  Grid.Row="0" Grid.Column="1"
                  Orientation="Vertical"
                  HorizontalOptions="Fill"
                  VerticalOptions="Fill"
                  >
                  <Label
                    Text ="{Binding 創業空間名稱}"
                    Margin="0,0,10,0"
                    FontSize="22"
                    HorizontalOptions="Start" VerticalOptions="Start"
                    LineBreakMode="MiddleTruncation"
                    />
                  <Label
                    Text ="{Binding 地址}"
                    Margin="0,0,10,0"
                    FontSize="14"
                    HorizontalOptions="Start" VerticalOptions="Start"
                    LineBreakMode="MiddleTruncation"
                    />
                  <Label
                    Text ="{Binding 使用坪數, StringFormat='坪數: {0}'}"
                    Margin="50,0,10,0"
                    FontSize="18"
                    HorizontalOptions="End" VerticalOptions="Start"
                    LineBreakMode="HeadTruncation"
                    />
                </StackLayout>

              </Grid>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </Grid>

</ContentPage>

檢視模型部分

  1. 在核心PCL XFCreative 專案內,開啟 ViewModels 資料夾內的BusinessSpaceDetailPageViewModel.cs 檔案。
  2. 在建構式內,加入底下程式碼
    這兩個 DelegateCommand 物件,將會提供檢視內的 Command 綁定屬性要執行的方法,例如,在 查看空間資訊,將會產生一個 網頁資料NodeViewModel 物件,接著把要顯示的 HTML 標題與本文設定到這個物件內,並且透過另外產生的 NavigationParameters 物件,將這個資訊傳遞到新的頁面內,這個就是切換頁面與傳遞參數的使用方式 await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
            查看空間資訊Command = new DelegateCommand(查看空間資訊);
            查看價格方案Command = new DelegateCommand(查看價格方案);
        private async void 查看空間資訊()
        {
            var fooNavigationParameters = new NavigationParameters();
            var fooItem = new 網頁資料NodeViewModel()
            {
                標題名稱 = "空間資訊",
                網頁內容 = 創業空間明細.空間資訊,
            };

            fooNavigationParameters.Add("網頁資料NodeViewModel", fooItem);
            await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
        }
  1. 使用底下完整程式碼替換掉剛剛開啟的檔案內容

BusinessSpaceDetailPageViewModel.cs

using Newtonsoft.Json;
using Plugin.ExternalMaps;
using Plugin.Messaging;
using Plugin.Share;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using XFCreative.Models;
using XFCreative.Services;

namespace XFCreative.ViewModels
{
    public class BusinessSpaceDetailPageViewModel : BindableBase, INavigationAware
    {
        private readonly INavigationService _navigationService;

        public DelegateCommand 查看空間資訊Command { get; set; }
        public DelegateCommand 查看價格方案Command { get; set; }

        private 創業空間明細 _創業空間明細;
        public 創業空間明細 創業空間明細
        {
            get { return _創業空間明細; }
            set { SetProperty(ref _創業空間明細, value); }
        }
        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public BusinessSpaceDetailPageViewModel(INavigationService navigationService)
        {
            // 取得頁面導航的實作
            _navigationService = navigationService;

            查看空間資訊Command = new DelegateCommand(查看空間資訊);
            查看價格方案Command = new DelegateCommand(查看價格方案);
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("創業空間Selected"))
            {
                var foo創業空間Selected = parameters["創業空間Selected"] as 創業空間NodeViewModel;
                系統初始化(foo創業空間Selected);
            }

        }

        public void 系統初始化(創業空間NodeViewModel 創業空間NodeViewModel)
        {
            var fooItem = GlobalData.創業空間Repository.Items.FirstOrDefault(x => x.創業空間名稱 == 創業空間NodeViewModel.創業空間名稱);
            if (fooItem != null)
            {
                創業空間明細 = new 創業空間明細()
                {
                    創業空間名稱 = fooItem.創業空間名稱,
                    使用坪數 = fooItem.使用坪數,
                    使用時間 = fooItem.使用時間,
                    修改時間 = fooItem.修改時間,
                    備註 = fooItem.備註,
                    價格方案 = fooItem.價格方案,
                    創業空間類型 = fooItem.創業空間類型,
                    地址 = fooItem.地址,
                    官方網站 = fooItem.官方網站,
                    座標經度 = fooItem.座標經度,
                    座標緯度 = fooItem.座標緯度,
                    建物現況 = fooItem.建物現況,
                    建立時間 = fooItem.建立時間,
                    建築類型 = fooItem.建築類型,
                    建造材質 = fooItem.建造材質,
                    所屬單位 = fooItem.所屬單位,
                    招募團隊類型 = fooItem.招募團隊類型,
                    樓別樓高 = fooItem.樓別樓高,
                    標籤 = fooItem.標籤,
                    空間主照片 = fooItem.空間主照片,
                    空間是否出租 = fooItem.空間是否出租,
                    空間資訊 = fooItem.空間資訊,
                    縣市區域 = fooItem.縣市區域,
                    聯絡email = fooItem.聯絡email,
                    聯絡人 = fooItem.聯絡人,
                    詳細照片 = fooItem.詳細照片,
                    連絡電話 = fooItem.連絡電話,
                    進駐使用人數 = fooItem.進駐使用人數,
                };
            }
        }

        private async void 查看空間資訊()
        {
            var fooNavigationParameters = new NavigationParameters();
            var fooItem = new 網頁資料NodeViewModel()
            {
                標題名稱 = "空間資訊",
                網頁內容 = 創業空間明細.空間資訊,
            };

            fooNavigationParameters.Add("網頁資料NodeViewModel", fooItem);
            await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
        }

        private async void 查看價格方案()
        {
            var fooNavigationParameters = new NavigationParameters();
            var fooItem = new 網頁資料NodeViewModel()
            {
                標題名稱 = "價格方案",
                網頁內容 = 創業空間明細.價格方案,
            };

            fooNavigationParameters.Add("網頁資料NodeViewModel", fooItem);
            await _navigationService.Navigate("WebView更多資訊Page", fooNavigationParameters);
        }

    }
}

產生將文字內容軟換成為 HtmlWebViewSource 的數值轉換器 (Value Converter)

  1. 在核心PCL XFCreative 專案內,使用滑鼠右鍵點選 Converters 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFCreative 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 StringToHtmlConverter,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

StringToHtmlConverter.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XFCreative.Converters
{
    public class StringToHtmlConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var fooUrl = value as string;
            var htmlSource = new HtmlWebViewSource();
            htmlSource.Html = fooUrl;

            return htmlSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

設定 XAML 全域資源

  1. 在核心PCL XFCreative 專案內,開啟 App.xaml 檔案。
  2. 使用底下程式碼替換掉剛剛開啟的檔案內容

App.xaml

<?xml version="1.0" encoding="utf-8" ?>
<prism:PrismApplication 
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:prism="clr-namespace:Prism.Unity;assembly=Prism.Unity.Forms"
  xmlns:Converter="clr-namespace:XFCreative.Converters;assembly=XFCreative"
  x:Class="XFCreative.App">

  <Application.Resources>
    <ResourceDictionary>
       <Converter:StringToHtmlConverter x:Key="StringToHtmlConverter" />
    </ResourceDictionary>
  </Application.Resources>

</prism:PrismApplication>

執行結果

Android 執行結果

請在方案總管內,滑鼠右擊 XFCreative.Droid 專案,選擇 設定為起始專案,接著按下 F5 開始執行。
顯示清單項目明細1 顯示清單項目明細2
顯示清單項目明細3 顯示清單項目明細4