本文章是由機器翻譯。

Xamarin

執行並在 Xamarin 中使用資料繫結

Laurent Bugnion

下載代碼示例

資料繫結是一個流行的概念,在程式設計這幾天,尤其是對用戶端應用程式中。在這篇文章中,我將討論哪些資料繫結是和它如何使用本機,如 Windows XAML 支援它的技術。我蓋可觀察的屬性,資料繫結和如何這些可用於不支援資料繫結"開箱即用"的技術的基本原理後,看看如何可以將資料繫結支援添加到 Xamarin.Android 和 Xamarin.iOS 使用 MVVM 光工具組 (mvvmlight.net)。這個羽量級的工具組是最受歡迎的模型-視圖-模型 (MVVM) 框架,為Windows Presentation Foundation(WPF)、 Silverlight、 Windows Phone、 Windows 應用商店、 Xamarin.Android、 Xamarin.iOS、 Xamarin.Forms 和更多的平臺。

我會總結討論的是 Xamarin.Forms,新加入的 Xamarin 框架,它允許您一次,生成在 XAML 中的 UI 並運行 Android、 iOS 和 Windows Phone 中的資料繫結。

什麼資料繫結?

資料繫結是連接 UI 和業務邏輯的過程。通過資料繫結兩個連接的屬性將保持同步。這是偉大的因為當您更改物件 (資料模型,通常被稱為 ViewModel) 上的值,在 UI 中相應的屬性也將會自動更新。同樣,如果要"雙向"資料繫結,在 UI 中的值的修改將自動能更新 ViewModel,以及。資料繫結已經可供用戶端應用程式一段時間,即使之前介紹了 WPF 和所有其他基於 XAML 的技術。例如,ASP.NETWeb 表單中資料控制項 (如清單方塊中可以將資料繫結到需要在螢幕上代表的項的集合。為了"轉化"的資料項目目的視覺化表示形式,通常定義專案範本。這是一個小片段的 HTML 代碼中的某些控制項顯示資料項目目的屬性中包含的值。

在 XAML 中,這一概念已擴展和它是合理的說法每個 XAML 開發人員將使用資料繫結或大或小的程度上。雖然它可以是誘人的 (尤其是對於開發人員來自不支援這種機制的更多傳統技術),一次處理大部分的資料模型更改在原始程式碼中直接掌握了資料繫結的權力幾乎不可能再去寫在原始程式碼中的資料更改管理的繁瑣過程。

不僅僅是資料控制項

XAML 資料繫結是為更多"只是"資料控制項。它允許將任何物件的任何屬性綁定到任何其他屬性。(請記住只是屬性的一種特殊稱為依賴項屬性 [DP] 可以是屬性的資料繫結的目標。存款保障計畫中不存在 Android 和 iOS,這就是為什麼可用的資料繫結框架使用一些替代方法。)

資料繫結看到採用的框架,例如 KnockoutJS 和 AngularJS,功能在後臺運行的 JavaScript 代碼的資料繫結擴展 Web 世界的興趣重燃。這些資料繫結框架重啟發了 XAML 的框架,它是有趣的看到一大群人,採用的原則 (如 MVVM 模式),已由 XAML 社區。

一個聲明的過程

像 XAML 和 HTML 標籤技術被稱為聲明式的因為它們允許您為使用者介面"宣佈"你的意圖。這是在不同時間點上比代碼實現,通常做,有時甚至由不同的團隊。例如,在 XAML 技術 UI 開發人員負責 XAML 被稱為"集成"或有時"地產商的互動,"或甚至野蠻"devsigner"。此角色意味著設計師的視覺的應用程式,很好地理解,即使集成商往往是開發商,他們坐在兩把椅子之間,應用程式開發中有較強的創新責任。

由於資料繫結中,有可能甚至在小型開發團隊強烈區分 UI 創造的過程。當我工作的小應用程式,在那裡我唯一開發商時,我想說我在開發過程中切換的帽子。當代碼包括資料模型、 資料服務心的我工作時,我就穿我開發的帽子。當我切換到創建 UI 時,然後更改給我積分的帽子。

這種分離的角色反映了分離關注點,通常是可取的在現代軟體發展中。雖然資料繫結並不絕對需要這種分離,它是非常方便的方法,説明你進入正確的心態。

有 Xamarin 中的資料繫結嗎?

就像在 Windows Phone Xamarin.Android 和 Xamarin.iOS 允許 UI,以建在原始程式碼中直接,但也提供了一個更現代的方法與聲明性標記中使用的 XML 檔。在 Android 中,這是一個 AXML 的檔 ; 在 iOS 中一種方便的方法是使用演示圖板檔。這是類似于我們在 Windows Phone 與 XAML 中做了什麼。注意到這些聲明性標記檔並不特定于 Xamarin ; 它們也用香草的 Android 和 iOS 開發中。

雖然方便 (尤其是因為它們允許使用類似的 Xamarin 工作室或Visual Studio提供的視覺化設計器工具) 的聲明性標記檔在 Android、 iOS 都比 XAML 不那麼強大。尤其是,他們缺乏 XAML 所要求的標記擴展。這種運算式括在大括弧 ({}) 內。有大量的這些擴展,例如,訪問資源位於在 XAML 文檔中或創建一個資料繫結,此代碼片斷所示:

<Button Content="{Binding ButtonContent}"
        Command="{Binding ExecuteCommand}"
        CommandParameter="{Binding IsChecked, ElementName=LockCheckBox}" />

此標記,是視圖的一部分,說一個按鈕控制項已綁定到源屬性稱為 ButtonContent,其內容屬性和其命令屬性綁定到一個名為 ExecuteCommand 的源屬性。這些源屬性都可以在任何物件作為預設資料或綁定上下文為該按鈕的父母 (通常是作為一個整體的頁面) 通常 ViewModel 物件。但是,您可以在任何您需要的級別設置綁定上下文。第三行的標記,例如,明確­它說,與此相應按鈕綁定到另一個元素校正屬性在頁,它的名字叫 LockCheckBox。

不幸的是,並不存在的資料繫結概念本身在 Android 和 iOS 所以,在本文的其餘部分,我將會向您展示如何可以實現這兩個平臺的資料繫結中的 Xamarin,然後如何 MVVM 光工具組提供了一種實現你可以使用來促進這一進程。此外,Xamarin 還提供了稱為 Xamarin.Forms 的 ui 使用類似于 Windows 的 XAML 標記語言擴展。Xamarin.Forms 支援綁定聲明標記中的直接,無需添加任何外部框架。

在 Android 和 iOS 中實現資料繫結

我要去構建一個小型的應用程式連接到一個簡單的資料服務,並返回一個清單的花朵,每一個都有一個名稱和描述。你會發現這種應用,名叫 XamDataBinding,在 galasoft.ch/s/xambinding。為簡單起見,我將集中精力只,一頁所示圖 1。此頁上,在 Android、 iOS 和 Windows Phone 中實現具有以下特點:

  • 花一個清單。理想情況下清單應該更新本身只要底層資料來源發生更改。
  • 用於刷新清單的按鈕。
  • 文本顯示的日期和上次刷新時間。
  • "鎖定"核取方塊或開關。此元素的目的相當不在生產場景中,但用於演示,有一定的道理,想像這"鎖"的刷新按鈕時它檢查。

樣品在 Android、 iOS 和 Windows Phone 中的應用
圖 1 樣品在 Android、 iOS 和 Windows Phone 中的應用

MVVM 模式依賴于一些簡單的原則:

  • 可觀測物件實現 INotifyPropertyChanged 介面。此.NET 介面公開的引發事件,應可觀察到的屬性修改時引發。
  • 可以在應用程式的過程中更改的清單應該存儲在 ObservableCollection < T > 實例。
  • 這樣一份名單引發 CollectionChanged 事件時其內容發生更改 (添加、 刪除或不同的排序次序)。
  • 某些物件公開功能的實現 ICommand 介面的屬性。此介面定義一個 Execute 方法和 CanExecute 方法。後者返回 true 或 false,具體取決於是否可以執行的 Execute 方法。此外,ICommand 指定的 CanExecute­Changed 事件。因為這有可能影響到綁定的 UI 控制項的狀態,當 CanExecute 方法的變化,返回的值中必須會引發此事件。

在 MVVM 光工具組,這些介面是由具體的類,如 ObservableObject 和 ViewModelBase (INotifyPropertyChanged) 和 RelayCommand (ICommand) 實現的。在 XamDataBinding 示例中,建立使用 MVVM 光工具組,並存儲在一個稱為 XamDataBinding.Data 的可擕式類庫中進行的模型和 ViewModel 層。 此庫可以 Xamarin 和視窗之間共用。

MVVM,在每個視圖是"驅動"由 ViewModel。在 Windows 和 Windows Phone,ViewModel 通常用作該 DataCoNtext,是一個屬性視圖 (頁面、 視窗、 UserControl 等等)。這是一種簡便方法使用資料繫結,而不必總是指定綁定的源。在 Android 和 iOS,那裡是沒有 DataCoNtext 的概念。相反,您聲明 ViewModel 視圖中的並直接使用它。XamDataBinding 樣品一樣的小應用程式,可以直接在視圖中創建 ViewModel (安卓系統,MainView 中的活動­控制器在 iOS 和在 Windows Phone 主頁):

private MainViewModel _vm;
public MainViewModel Vm
{
  get
  {
    return _vm ?? (_vm = new MainViewModel());
  }
}

執行具有約束力和指揮沒有一個框架

若要避免在一遍遍重複同樣的事情,我會在此集中的 XamDataBinding 樣品的 Android 應用程式。然而,完全相同的概念適用于 iOS 應用程式。由於這些平臺不支援資料繫結,我會執行綁定和手動指揮:

  • 檢查已更改的屬性的名稱和相應地更新視圖,我會處理在視圖中,MainViewModel 的引發事件。
  • 某些綁定在兩個方向 (雙向綁定) 去。例如,當按一下核取方塊時,在 MainViewModel 上相應的布林屬性需要更新。不具有約束力的框架,我需要訂閱核取方塊事件和更新從視圖中手動視圖模型的屬性。
  • 刷新按鈕必須在 MainViewModel 上執行 RefreshCommand。沒有一個指揮的框架,這一點,也必須被手動處理。我可以處理該按鈕的 Click 事件,並從視圖中直接調用命令的執行方法。
  • 最後,我知道該命令可以禁用它所綁定到的控制項。在這種情況下,如果沒有指揮的框架,我需要訂閱的命令可以­ExecuteChanged 事件。時觸發此事件,可以調用該命令的 CanExecute 方法,根據返回的值,啟用或禁用控制項。

這些步驟都不是很複雜的但整個過程可以是冗長而重複。在實踐中,很容易使用具有約束力和指揮的框架,如由 MVVM 光工具組提供。

使用 MVVM 光資料繫結框架

前面的示例中工作,但他們討厭寫,因為你必須處理的各項活動和思考的所有可能的方案。它們也是更難維護和理解,尤其是當有多個 UI 元素來處理。

簡單的資料繫結框架中使用 MVVM 光工具組,與此相反的是,允許您創建 UI 元素和代碼,以及使用者介面元素和命令之間的關係。由於此綁定框架下,可以創建綁定並附加到命令在 OnCreate 方法中,如中所示圖 2

圖 2 創建綁定和命令

_lastLoadedBinding = this.SetBinding(
  () => Vm.LastLoadedFormatted,
  () => LastLoadedText.Text);
_lockBinding = this.SetBinding(
  () => Vm.IsLocked,
  () => LockCheckBox.Checked,
  BindingMode.TwoWay);
_refreshCommandBinding = this.SetBinding(
  () => LockCheckBox.Checked);
RefreshButton.SetCommand("Click", Vm.RefreshCommand, _refreshCommandBinding);
FlowersList.Adapter = Vm.Flowers.GetAdapter(GetFlowerAdapter);

圖 2,第一次創建 MainViewModel 的 LastLoadedFormatted 屬性和 TextView 的 Text 屬性之間的單向綁定。這種單一的程式碼照顧建立這兩個屬性之間的長期關係。注意,使用擴充方法將綁定,這由 MVVM Light 提供。此方法返回創建的綁定實例。因為綁定物件用 WeakReferences 以避免記憶體洩漏編寫的這種綁定應保存為一個私有欄位來防止綁定獲取自動分離。

第二個語句創建的 MainViewModel 的 IsLocked 屬性與 LockCheckBox 選中的屬性之間的雙向綁定。請注意預設情況下,每個綁定都是單向的所以您必須指定雙向 BindingMode 將綁定方法中。

第三個語句創建一種特殊的約束力,只有源與沒有目標。來自 LockCheckBox 的檢查的屬性。我會在 SetCommand 方法中,使用此綁定,以指示 MainViewModel LoadCommand 應該被重新評估,每次 LockCheckBox 選中的屬性更改時。在 XAML 中,我將創建一個綁定在與此相應的按鈕上。在這裡,我使用一個類似的構造由創建綁定第一,,然後將此實例傳遞給 SetCommand 方法。

第四條語句上的 RefreshButton 設置的命令。雖然我處理 Click 事件在這裡,我其實可以開動任何 UI 元素的任何事件的命令。SetCommand 方法的第二個參數是必須驅動的命令。最後,第三個參數是可選的僅用於需要參數的命令。如前所述,我在這裡使用前面創建的綁定。

正在設置清單

最後,還有 ListView 在 UI 中。MVVM Light 提供一種稱為 GetAdapter,可以使用在任何 ObservableCollection 或任何 IList 上的非常有用的擴充方法。它返回一個 Android 的配接器,可以用作 ListView 配接器屬性。因為 MainViewModel 花屬性是 ObservableCollection,集合發生更改時將自動更新使用者介面:

FlowersList.Adapter = Vm.Flowers.GetAdapter(GetFlowerAdapter);

GetFlowerAdapter 方法,傳遞給 GetAdapter 方法時,用於獲取行認為,將代表一朵花。在這個例子中我把它簡單通過使用一個內置行視圖,以顯示圖片和花的名字圖 3 顯示。不過,我們會很容易的要使用更多的細節或不同的佈局來創建自訂行視圖。

如果我運行該應用程式現在,我會看到使用者介面中顯示圖 1。您可以嘗試以下功能:

  • 按一下鎖定核取方塊將禁用刷新按鈕。禁用通過 RefreshCommand 和 CanExecute 方法發生。檢查 MainViewModel 的代碼,看看如何做到這一點。請注意同樣的效果會在 XAML 中,是否您運行包含的 Windows Phone 應用程式。
  • 啟用刷新按鈕後,按一下它非同步載入清單中的花朵。注意連接到 Web 服務的代碼包含在 MainViewModel,並在此可移植類庫支援任何平臺上完全可以重複使用。
  • 載入清單後,將與"最後載入"資訊更新的 TextView 狀態。這,也是通過我創建的綁定。
  • 運行 iOS 或 Windows Phone 版本的應用程式創建完全相同的結果。在 iOS,在 MainViewController 的 ViewDidLoad 方法中創建綁定。在 Windows Phone,我創建了 MainPage.xaml 中的綁定。

圖 3 創建自訂的清單視圖行

private View GetFlowerAdapter(
  int position,
  FlowerViewModel flower,
  View convertView)
{
  if (convertView == null)
  {
    convertView = LayoutInflater.Inflate(
    Android.Resource.Layout.ActivityListItem, null);
  }
  var text = convertView.FindViewById<TextView>(Android.Resource.Id.Text1);
  text.Text = flower.Model.Name;
  var image = convertView.FindViewById<ImageView>(Android.Resource.Id.Icon);
  image.SetImageBitmap(GetImageBitmapFromUrl(flower.ImageUri.AbsoluteUri));
  return convertView;
}

Xamarin.Forms 中的資料繫結

去年,Xamarin 發佈的形式框架,允許共用代碼,也是 UI 中所有支援的平臺。這是理想的建設快速的使用者介面測試的代碼 ; 例如,在原型階段。表單框架也可以用於生產代碼例如,必須在多個平臺上運行的業務線應用程式。

與 Xamarin.Android 和 Xamarin.iOS,Xamarin.Forms 支援資料繫結本機。因為它還支援 XAML (雖然比在 WPF,Windows Phone 和 Windows 應用商店中可用的不同版本),可以直接寫在 XAML 標記中的資料繫結。這意味著您可以編寫這樣的事情:

<Label Text="{Binding LastLoadedFormatted}"
       VerticalOptions="Center"
       HorizontalOptions="Center" />

所包含的示例可以通過使用 Xamarin.Forms 和重用每個平臺上的使用者介面更加簡化。當然,對於應用程式在哪裡與使用者體驗必須採取額外的照顧,Xamarin.Forms 可能不是最佳的解決方案。但是,應用程式的整個範圍,表單將 UI 開發大大簡化,釋放你處理其他任務,如提高應用程式的性能和穩定性,添加功能,等等。

總結

MVVM Light 綁定有別于 XAML 綁定在它們創建代碼而不是標記中。但是,確保乾淨的 API,花費了好幾個小時。我借此機會感謝我的好朋友柯拉多沃利上綁定實現的支援和説明我創造一種盡可能接近到 XAML 綁定工作流的語法。

此外,對於他們的説明,我要感謝 Xamarin 乘員組和特別是JamesMontemagno 審查此綁定框架的早期版本,給了我超級寶貴的意見。

最後,為更多的資訊和一個完整代碼示例,包括 Windows Phone、 Xamarin.Android、 Xamarin.iOS 和 Xamarin.Forms,看看我 Xamarin 演變的演示文稿,在 galasoft.ch/s/evolve14


Laurent Bugnion 是使用 WPF、 Silverlight,Xbox,Kinect,Windows 應用商店、 Windows Phone、 Xamarin 和體驗等技術的 Microsoft 合作夥伴 IdentityMine 公司的高級主管他設在瑞士的蘇黎世。他也是微軟最有價值球員、 微軟區域主任和 Xamarin MVP。

感謝以下技術專家對本文的審閱:克賴希 Brockschmidt (Microsoft)、 規範埃斯 (Microsoft) 和JamesMontemagno (Xamarin)