訊息中心
例如:在 Xamarin.Forms 內,訊息中心使得 View Model 可以與其他類別物件通訊,而不需要知道這些物件的型別,雙方彼此只需要知道通訊的訊息合約內容即可。這樣的應用可以在這個專案範例中看到,
MainPageViewModel
與 MainPage
透過訊息中心訂閱了相同的訊息,當訊息發送出來之後,兩者都會同時收到,不過,任一方或者雙方,都可隨時取些訂閱這訊息。
因此,在訊息中心的架構下,共有兩個部分所組成:
- 訂閱 (
Subscribe
)當訂閱某個訊息,這表示需要隨時聆聽(Listen)是否有與其有關的訊息傳送進來,並且執行相關的動作。在 Xamarin.Forms 的訊息中心機制下,多個訂閱者可以同時聆聽同一個相同送出訊息。 - 傳送訊息 (
Send
)透過傳送訊息,告知其他該訊息的訂閱者,可以執行相關動作。
MainPage
- 在安裝好所有的擴充插件(Plugins),打開核心PCL 的 MainPage.xaml 檔案,將底下的 XAML 宣告定義複製到這個檔案內。
- 首先為了避免在 iOS 平台執行時候,最上方的狀態烈被遮蔽掉的問題,因此,透過
ContentPage.Padding
來定義整個頁面皆內縮 20dp。 - 這個頁面的控制項,使用了
ScrollView
版面配置來進行所有控制項的定位,因此,當螢幕無法顯示所有控制項的時候,使用者可以透過手勢滑動螢幕的操作方式,看到其他內容。 - 在這個 XAML 中,使用到的
ContentPage.Resources
功能,在這裡所宣告的內容,都可以直接在這個頁面內來引用;其中,<x:Double x:Key="TopicLabelFontSize">30</x:Double>
這個是宣告了一個Double
型別的物件,他的值為 30,在其他控制項若要參考這個物件,可以使用StaticResource
這個延伸標記功能取得這個物件值。 - 在這個頁面內,定義了大量的
Label
控制項,並且都有定義x:Name
延伸標記,而這個延伸標記是用於讓 code-behind 的C#程式碼,可以存取到這個控制項。因此,實際的處理邏輯,都存在 code-behind 程式碼內。
MainPage.xaml
這個頁面 XAML 宣告內容相當的簡單。在 StackLayout 版面配置下,定義了三個按鈕與一個 ListView。
<?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:local="clr-namespace:XFMessage"
x:Class="XFMessage.MainPage">
<StackLayout
Orientation="Vertical"
HorizontalOptions="Start" VerticalOptions="Center">
<Button x:Name="button說嗨" Text="說嗨" Clicked="Onbutton說嗨Click"/>
<Button x:Name="button對約翰說嗨" Text="對約翰說嗨" Clicked="Onbutton對約翰說嗨Click"/>
<Button x:Name="button停止訂閱顯示警告" Text="停止訂閱顯示警告" Clicked="Onbutton停止訂閱顯示警告Click"/>
<ListView x:Name="listView" />
</StackLayout>
</ContentPage>
- 請將下列 C# 程式碼複製到 MainPage.xaml.cs內。
- 在建構式內,設定這個頁面的
BindingContext
屬性是一個MainPageViewModel
型別的物件;作為所有頁面控制項的資料綁定來源。另外,在建構式內也訂閱了訊息中心的一個有參數的訊息,當街收到這類訊息之後,就會顯示一個警告對話窗。 Onbutton停止訂閱顯示警告Click
按鈕事件則是處理取消訂閱訊息事件,也就是當按下這個按鈕之後,就不再會看到警告訊息對話窗了。
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFMessage
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
// Subscribe to a message (which the ViewModel has also subscribed to) to pop up an Alert
MessagingCenter.Subscribe<MainPage, string>(this, "Hi", (sender, arg) => {
DisplayAlert("接收到訊息", "參數=" + arg, "OK");
});
listView.SetBinding(ListView.ItemsSourceProperty, "Greetings");
}
void Onbutton說嗨Click(object sender, EventArgs e)
{
MessagingCenter.Send<MainPage>(this, "Hi");
}
void Onbutton對約翰說嗨Click(object sender, EventArgs e)
{
MessagingCenter.Send<MainPage, string>(this, "Hi", "約翰");
}
void Onbutton停止訂閱顯示警告Click(object sender, EventArgs e)
{
MessagingCenter.Unsubscribe<MainPage, string>(this, "Hi");
DisplayAlert("停止訂閱",
"這個頁面已經停止接收訊息,所以,不再會出現任何警告內容;然而, ViewModel 仍然會繼續接收訊息",
"OK");
}
}
}
MainPageViewModel
- 請在核心PCL專案節點使用滑鼠右擊,選擇
加入
>類別
,接著在名稱欄位旁的文字輸入盒中,填入MainPageViewModel
。最後,請將底下程式碼複製到剛剛產生的檔案內。 MainPageViewModel
這個類別,是 MVVM 架構下的 ViewModel,也就是負責與 View 介接的類別,在這個範例中,這個MainPageViewModel
提供了整個 MainPage 頁面中的資料繫結來源,因此,可以在 MainPage 的建構式內,看到BindingContext
這個屬性的值,設定為new MainPageViewModel();
。而在這個頁面中的ListView
控制項的資料來源,也是由MainPageViewModel
這個 ViewModel 所提供的。- 這個 ViewModel 內,定義了一個
ObservableCollection<string>
類別物件,作為 ListView 控制項的資料來源。而在建構式中,訂閱了兩個訊息,一個是有傳遞參數的,一個是沒有傳遞參數的。不論是哪一個,當街收到所送出的訊息通知,就會在相對應的處理事件中,將所接收到的訊息內容,加入到ListView
內。
MainPageViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFMessage
{
public class MainPageViewModel
{
public ObservableCollection<string> Greetings { get; set; }
public MainPageViewModel()
{
Greetings = new ObservableCollection<string>();
MessagingCenter.Subscribe<MainPage>(this, "Hi", (sender) => {
Greetings.Add("Hi");
});
MessagingCenter.Subscribe<MainPage, string>(this, "Hi", (sender, arg) => {
Greetings.Add("Hi " + arg);
});
}
}
}
實際執行畫面
Android 執行結果
請在方案總管內,滑鼠右擊
XFMessage.Droid
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。
點選
說嗨
按鈕,此時,在 MainPageViewModel
內訂閱的訊息,就會將所接收到的訊息,加入到 ListView。
點選
對約翰說嗨
按鈕,此時,在 MainPageViewModel
內訂閱的訊息,就會將所接收到的訊息,加入到 ListView。另外,在 MainPage
內訂閱的事件,則是會顯示出警告對話視窗。
點選
停止訂閱顯示警告
按鈕,此時,會取消 MainPage
內訂閱的訊息,下次按下 對約翰說嗨
按鈕,則是不會顯示出警告對話視窗。
因為已經取消
MainPage
內訂閱的訊息,此時按下 對約翰說嗨
按鈕,不會顯示出警告對話視窗。
佈署注意事項
iOS 執行結果
請在方案總管內,滑鼠右擊
XFMessage.iOS
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。
點選
說嗨
按鈕,此時,在 MainPageViewModel
內訂閱的訊息,就會將所接收到的訊息,加入到 ListView。
點選
對約翰說嗨
按鈕,此時,在 MainPageViewModel
內訂閱的訊息,就會將所接收到的訊息,加入到 ListView。另外,在 MainPage
內訂閱的事件,則是會顯示出警告對話視窗。
點選
停止訂閱顯示警告
按鈕,此時,會取消 MainPage
內訂閱的訊息,下次按下 對約翰說嗨
按鈕,則是不會顯示出警告對話視窗。
因為已經取消
MainPage
內訂閱的訊息,此時按下 對約翰說嗨
按鈕,不會顯示出警告對話視窗。
MessagingCenter
),透過訊息中心這個機制,可以減少 Xamarin.Forms 程式開發的耦合性,也就是說,讓各個類別間不要有關聯關係。在訊息中心機制內,包含了簡單的訊息傳送與接收服務。