在上一個練習中,您已經可以透過網路取得創業空間的相關資料,並且顯示到螢幕上,接下來,在這個練習中,您將須要讓使用者在點選創業空間清單項目的時候,可以取得使用者是點選哪個項目,並且導航到另外一個頁面,將所選擇的資料明細顯示出來。
在這個階段的練習,您將會學會底下的 Xamarin.Forms 的開發技術:
- 建立創業空間項目的詳細頁面檢視與檢視模型
- 建立可以顯示 HTML 內容的頁面檢視與檢視模型
- 註冊此次新加入的 View
- 使用 XAML (行為)Behavior 與命令 (ICommand)
- 產生將文字內容軟換成為 HtmlWebViewSource 的數值轉換器 (Value Converter)
- 設定 XAML 全域資源
建立創業空間明細模型
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選ViewModels
資料夾,接著,選擇加入
>類別
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>類別
- 在底下名稱欄位內,輸入
創業空間明細ViewModel
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
創業空間明細ViewModel.cs
- 這個類別
創業空間明細
將會用來定義在顯示在資料明細頁面上的檢視模型。
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
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選Views
資料夾,接著,選擇加入
>新增項目
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>Prism
>Prism ContentPage (Forms)
- 在底下名稱欄位內,輸入
BusinessSpaceDetailPage
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
BusinessSpaceDetailPage.xaml
- 在這裡的根項目 (Root Element) 使用的是
ContentPage
- 在這個頁面內,有兩個
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
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選ViewModels
資料夾,接著,選擇加入
>類別
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>類別
- 在底下名稱欄位內,輸入
BusinessSpaceDetailPageViewModel
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
BusinessSpaceDetailPageViewModel.cs
- 在
BusinessSpaceDetailPageViewModel
類別內,透過OnNavigatedTo
事件方法取得了要顯示資料的參數,您可以透過NavigationParameters
資料字典取得所傳遞進來的資料,並且透過系統初始化
方法,把要顯示的資料產生在相對應的檢視模型物件內。 - 在建構式內,使用
DelegateCommand
產生了兩個DelegateCommand
的委派方法,這兩個方法會當使用者按下畫面中的按鈕,就會來執行相對應的方法。 查看空間資訊()
與查看價格方案()
方法內,展示了如何導航到另外一個頁面,並且如何傳遞參數到新的頁面。這裡是透過了產生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);
}
}
}
建立網頁資料 檢視模型
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選ViewModels
資料夾,接著,選擇加入
>類別
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>類別
- 在底下名稱欄位內,輸入
網頁資料NodeViewModel
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
網頁資料NodeViewModel.cs
- 這個類別
網頁資料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
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選Views
資料夾,接著,選擇加入
>新增項目
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>Prism
>Prism ContentPage (Forms)
- 在底下名稱欄位內,輸入
WebView更多資訊Page
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
WebView更多資訊Page.xaml
- 在這裡的根項目 (Root Element) 使用的是
ContentPage
- 這個頁面由
StackLayout
版面控制項目來進行配置Label
&WebView
這兩個控制項要顯示與排列方向 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
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選ViewModels
資料夾,接著,選擇加入
>類別
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>類別
- 在底下名稱欄位內,輸入
WebView更多資訊PageViewModel
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
WebView更多資訊PageViewModel.cs
- 在
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
- 在核心PCL
XFCreative
專案內,開啟App.xaml.cs
檔案 - 使用底下程式碼替換掉剛剛開啟的檔案內容
App.xaml.cs
- 若您沒有進行底下程式碼的修正,若開始執行該專案,就會產生錯誤訊息:
System.InvalidOperationException: HomePage could not be created. Please make sure you have registered HomePage for navigation.
- 在 App 類別的
RegisterTypes
方法中,您需要把HomePage
與BusinessSpacePage
這兩個檢視 (View) 註冊到 Unity 的容器內,這樣,當要導航到這些頁面的時候,Unity 容器將會自動解析出所要導航的頁面物件,並且自動進行相對應的檢視模型(ViewModel)的繫結與綁定動作。 - 另外,在建構式內,當要切換到頁面
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 內的頁面都寫好了,最後,就是要修改之前寫好的清單頁面,讓使用者在點選清單之後,可以將頁面切換到剛剛產生好的頁面。
- 在核心PCL
XFCreative
專案內,開啟Views
資料夾內的BusinessSpacePage.xaml
檔案。 - 請在
<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>
- 使用底下完整程式碼替換掉剛剛開啟的檔案內容
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>
檢視模型部分
- 在核心PCL
XFCreative
專案內,開啟ViewModels
資料夾內的BusinessSpaceDetailPageViewModel.cs
檔案。 - 在建構式內,加入底下程式碼這兩個
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);
}
- 使用底下完整程式碼替換掉剛剛開啟的檔案內容
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)
- 在核心PCL
XFCreative
專案內,使用滑鼠右鍵點選Converters
資料夾,接著,選擇加入
>類別
- 在
加入新項目 - XFCreative
對話窗中,點選Visual C#
>類別
- 在底下名稱欄位內,輸入
StringToHtmlConverter
,接著,點選新增
按鈕 - 使用底下程式碼替換掉剛剛產生的檔案內容
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 全域資源
- 在核心PCL
XFCreative
專案內,開啟App.xaml
檔案。 - 使用底下程式碼替換掉剛剛開啟的檔案內容
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
開始執行。