WPF 與 Xamarin.Forms 應用程式生命週期

Xamarin.Forms 會從 XAML 架構取得許多設計指引,而 XAML 架構之前,尤其是 WPF。 然而,在其他方面,它明顯偏離,這可能成為試圖遷移的人的粘性點。 本文件會嘗試找出其中一些問題,並在可能的情況下提供指引,將 WPF 知識橋接至 Xamarin.Forms。

應用程式生命週期

WPF 與 Xamarin.Forms 之間的應用程式生命周期類似。 兩者都會在外部 (platform) 程式代碼中啟動,並透過方法呼叫啟動 UI。 差異在於,Xamarin.Forms 一律會在平臺特定元件中啟動,然後初始化並建立應用程式的UI。

WPF

  • Main method > App > MainWindow

注意

根據預設,此方法 Main 會在程式碼中自動產生且不可見。

Xamarin.Forms

  • iOSMain method > AppDelegate > App > ContentPage
  • AndroidMainActivity > App > ContentPage
  • UWPMain method > App(UWP) > MainPage(UWP) > App > ContentPage

應用程式類別

WPF 和 Xamarin.Forms 都有一個 Application 類別,其會建立為單一類別。 在大部分情況下,應用程式會衍生自此類別以提供自定義應用程式,不過 WPF 中並非絕對必要。 兩者 Application.Current 都會公開 屬性來找出所建立的單一。

全域屬性 + 持續性

WPF 和 Xamarin.Forms 都有可用的 Application.Properties 字典,您可以在其中儲存可在應用程式中任何地方存取的全域應用層級物件。 主要差異在於,Xamarin.Forms 會在 暫停應用程式時保存 儲存在集合中的任何基本類型,並在重新啟動時重載它們。 WPF 不會自動支援該行為-相反地,大部分開發人員依賴隔離儲存區,或利用內 Settings 建支援。

定義頁面和可視化樹狀結構

WPF 會使用 Window 作為任何最上層視覺專案的根元素。 這會定義 Windows 世界中要顯示資訊的 HWND。 您可以在 WPF 中同時建立和顯示盡可能多的視窗。

在 Xamarin.Forms 中,頂層視覺效果一律由平台定義,例如在 iOS 上,它是 UIWindow。 Xamarin.Forms 會使用 Page 類別,將它的內容轉譯成這些原生平臺表示法。 Xamarin.Forms 中的每 Page 一個都代表應用程式中唯一的「頁面」,一次只能顯示一個頁面。

WPF Window 和 Xamarin.Forms Page 都包含一個 Title 屬性來影響顯示的標題,而且兩者都有 Icon 屬性可顯示頁面的特定圖示(請注意 ,Xamarin.Forms 中不一定會顯示標題和圖示)。 此外,您可以在背景色彩或影像等兩者上變更常見的視覺屬性。

在技術上,可以轉譯成兩個不同的平台檢視(例如,定義兩 UIWindow 個物件,並將第二個轉譯轉譯為外部顯示器或 AirPlay),它需要平臺特定的程式代碼才能這麼做,而且不是 Xamarin.Forms 本身直接支援的功能。

檢視

這兩個架構的視覺階層很類似。 WPF 由於對 WYSIWYG 文件的支援而更深一點。

WPF

DependencyObject - base class for all bindable things
   Visual - rendering mechanics
      UIElement - common events + interactions
         FrameworkElement - adds layout
            Shape - 2D graphics
            Control - interactive controls

Xamarin.Forms

BindableObject - base class for all bindable things
   Element - basic parent/child support + resources + effects
      VisualElement - adds visual rendering properties (color, fonts, transforms, etc.)
         View - layout + gesture support

檢視生命週期

Xamarin.Forms 主要針對行動案例。 因此,當使用者與其互動時,應用程式會 啟動暫停重新啟用 。 這類似於在 Window WPF 應用程式中按兩下 ,而且有一組方法和對應的事件,您可以覆寫或連結以監視此行為。

目的 WPF 方法 Xamarin.Forms 方法
初始啟用 ctor + Window.OnLoaded ctor + Page.OnStart
已顯示 Window.IsVisibleChanged Page.Appearing
已隱藏 Window.IsVisibleChanged Page.Disappearing
暫停/遺失焦點 Window.OnDeactivated Page.OnSleep
Activated/Got focus Window.OnActivated Page.OnResume
已關閉 Window.OnClosing + Window.OnClosed n/a

兩者也都支持隱藏/顯示子控件,在 WPF 中,它是三狀態屬性 IsVisible (可見、隱藏和折疊)。 在 Xamarin.Forms 中,它只是透過 IsVisible 屬性可見或隱藏。

版面配置

版面配置發生在 WPF 中發生的相同 2 階段 (Measure/Arrange) 中。 您可以覆寫 Xamarin.Forms Page 類別中的下列方法,以鏈接至頁面配置:

方法 目的
OnChildMeasureInvalidated 子系的慣用大小已變更。
OnSizeAllocated 頁面已獲指派寬度/高度。
LayoutChanged 事件 頁面的版面配置/大小已變更。

目前沒有呼叫的全域版面配置事件,WPF 中也沒有像這樣的全域 CompositionTarget.Rendering 事件。

一般版面配置屬性

WPF 和 Xamarin.Forms 都支援Margin控制元素周圍的間距,以及Padding控制元素內的間距。 此外,大部分的 Xamarin.Forms 版面配置檢視都有可控制間距的屬性(例如列或欄)。

此外,大部分元素都有屬性來影響它們在父容器中的位置:

WPF Xamarin.Forms 目的
HorizontalAlignment HorizontalOptions Left/Center/Right/Stretch 選項
VerticalAlignment VerticalOptions Top/Center/Bottom/Stretch 選項

注意

這些屬性的實際解譯取決於父容器。

版面配置檢視

WPF 和 Xamarin.Forms 都使用版面配置控件來放置子元素。 在大部分情況下,這些功能在功能方面彼此非常接近。

WPF Xamarin.Forms 版面配置樣式
StackPanel \(英文\) StackLayout 由左至右,或由上至下無限堆棧
方格 方格 表格式格式 (列和資料列)
DockPanel n/a 停駐到窗口邊緣
畫布 AbsoluteLayout 圖元/座標定位
WrapPanel n/a 包裝堆疊
n/a RelativeLayout 相對規則型定位

注意

Xamarin.Forms 不支援 GridSplitter

這兩個平臺都使用 附加屬性 來微調子系。

轉譯

WPF 和 Xamarin.Forms 的轉譯機制截然不同。 在 WPF 中,您建立的控制件會在畫面上將內容直接轉譯為圖元。 WPF 會維護兩個物件圖形(狀結構)來表示這個 -- 邏輯樹狀結構代表程式代碼或 XAML 中所定義的控件,而可視化樹狀結構代表直接由視覺元素(透過虛擬繪製方法)或可取代或自定義的 XAML 定義ControlTemplate在螢幕上執行的實際轉譯。 一般而言,可視化樹狀結構較為複雜,因為它包含控件周圍的框線、隱含內容的標籤等。WPF 包含一組 API(LogicalTreeHelperVisualTreeHelper)來檢查這兩個物件圖形。

在 Xamarin.Forms 中,您在 中 Page 定義的控件實際上只是簡單的數據物件。 它們類似於邏輯樹狀結構表示法,但絕不會自行轉譯內容。 相反地 ,它們是影響元素轉譯的數據模型 。 實際轉譯是由一 個別的視覺轉譯器 來完成,這些轉譯器會對應至每個控件類型。 這些轉譯器會依平臺特定的 Xamarin.Forms 元件,在每個平臺特定項目中註冊。 您可以在這裡看到清單。 除了取代或擴充轉譯器之外,Xamarin.Forms 也支援 Effects ,可用來影響每個平臺的原生轉譯。

邏輯/可視化樹狀結構

沒有公開的 API 可逐步執行 Xamarin.Forms 中的邏輯樹狀結構,但您可以使用 反思 ion 來取得相同的資訊。 例如, 以下是可列舉具有反映之邏輯子系 的方法。

圖形

Xamarin.Forms 包含用於繪製基本類型的圖形系統,稱為 Shapes。 如需 Shapes 的詳細資訊,請參閱 Xamarin.Forms Shapes。 此外,您可以包含第三方連結庫,例如 SkiaSharp 來取得跨平臺 2D 繪圖。

資源

WPF 和 Xamarin.Forms 都有資源和資源字典的概念。 您可以將任何物件類型放入 ResourceDictionary 具有索引鍵的 中,然後查閱 {StaticResource} 不會變更的專案,或 {DynamicResource} 查詢可在運行時間在字典中變更的專案。 使用方式和機制相同,但有一個差異:Xamarin.Forms 會要求您定義 ResourceDictionary 指派給 屬性的 Resources ,而 WPF 會預先建立屬性,併為您指派它。

例如,請參閱下列定義:

WPF

<Window.Resources>
   <Color x:Key="redColor">#ff0000</Color>
   ...
</Window.Resources>

Xamarin.Forms

<ContentPage.Resources>
   <ResourceDictionary>
      <Color x:Key="redColor">#ff0000</Color>
      ...
   </ResourceDictionary>
</ContentPage.Resources>

如果您未定義 ResourceDictionary,則會產生運行時錯誤。

樣式

Xamarin.Forms 中也完全支持樣式,可用來設定構成 UI 之 Xamarin.Forms 元素的主題。 它們支援觸發程式(屬性、事件和數據)、透過 BasedOn的 繼承,以及值的資源查閱。 樣式會透過 屬性明確 Style 套用至專案,或透過未提供資源索引鍵以隱含方式套用至專案,就像WPF 一樣。

裝置樣式

WPF 有一組預先定義的屬性(儲存為靜態值在一組靜態類別上,例如 SystemColors),以值和資源索引鍵的形式指定系統色彩、字型和計量。 Xamarin.Forms 很類似,但會定義一組 裝置樣式 來代表相同的專案。 這些樣式是由架構提供,並根據運行時間環境設定為值(例如輔助功能)。

WPF

<Label Text="Title" Foreground="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" />

Xamarin.Forms

<Label Text="Title" Style="{DynamicResource TitleStyle}" />