在 Xamarin 中的執行時間載入 XAMLLoading XAML at Runtime in Xamarin.Forms

下載範例 下載範例Download Sample Download the sample

Xamarin.Forms.Xaml命名空間包含兩個LoadFromXaml擴充方法,可在執行時間用來載入和剖析 XAML。The Xamarin.Forms.Xaml namespace includes two LoadFromXaml extension methods that can be used to load, and parse XAML at runtime.

背景Background

當構造了 Xamarin XAML 類別時,會間接呼叫LoadFromXaml方法。When a Xamarin.Forms XAML class is constructed, the LoadFromXaml method is indirectly called. 之所以會發生這種情況,是因為 XAML 類別的程式碼後置檔案會從其函式呼叫 InitializeComponent 方法:This occurs because the code-behind file for a XAML class calls the InitializeComponent method from its constructor:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}

當 Visual Studio 建立包含 XAML 檔案的專案時,它會剖析 XAML 檔案,以產生C#包含 InitializeComponent 方法定義的程式碼檔案(例如, MainPage.xaml.g.cs):When Visual Studio builds a project containing a XAML file, it parses the XAML file to generate a C# code file (for example, MainPage.xaml.g.cs) that contains the definition of the InitializeComponent method:

private void InitializeComponent()
{
    global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainPage));
    ...
}

InitializeComponent 方法會呼叫LoadFromXaml方法,從 .NET Standard 程式庫解壓縮 XAML 檔案(或其編譯的二進位檔)。The InitializeComponent method calls the LoadFromXaml method to extract the XAML file (or its compiled binary) from the .NET Standard library. 解壓縮之後,它會初始化 XAML 檔案中定義的所有物件,並將它們全部連接在父子式關聯性中,將程式碼中定義的事件處理常式附加至 XAML 檔案中設定的事件,並將物件的結果樹狀結構設定為的內容本頁.After extraction, it initializes all of the objects defined in the XAML file, connects them all together in parent-child relationships, attaches event handlers defined in code to events set in the XAML file, and sets the resultant tree of objects as the content of the page.

在執行時間載入 XAMLLoading XAML at runtime

LoadFromXaml的方法會 public,因此可以從 Xamarin 應用程式呼叫以載入,並在執行時間剖析 XAML。The LoadFromXaml methods are public, and therefore can be called from Xamarin.Forms applications to load, and parse XAML at runtime. 這會允許應用程式從 web 服務下載 XAML、從 XAML 建立必要的視圖,並在應用程式中顯示這類案例。This permits scenarios such as an application downloading XAML from a web service, creating the required view from the XAML, and displaying it in the application.

警告

在執行時間載入 XAML 具有顯著的效能成本,通常應該避免。Loading XAML at runtime has a significant performance cost, and generally should be avoided.

下列程式碼範例顯示簡單的使用方式:The following code example shows a simple usage:

using Xamarin.Forms.Xaml;
...

string navigationButtonXAML = "<Button Text=\"Navigate\" />";
Button navigationButton = new Button().LoadFromXaml(navigationButtonXAML);
...
_stackLayout.Children.Add(navigationButton);

在此範例中,會建立Button實例,並從 string中定義的 XAML 設定其Text屬性值。In this example, a Button instance is created, with its Text property value being set from the XAML defined in the string. Button 接著會加入至已在該頁面的 XAML 中定義的StackLayoutThe Button is then added to a StackLayout that has been defined in the XAML for the page.

注意

LoadFromXaml的擴充方法可讓您指定泛型型別引數。The LoadFromXaml extension methods allow a generic type argument to be specified. 不過,很少需要指定型別引數,因為它會從其操作所在的實例型別推斷而來。However, it's rarely necessary to specify the type argument, as it will be inferred from the type of the instance its operating on.

LoadFromXaml方法可以用來擴充任何 XAML,下列範例會因而誇大ContentPage然後流覽至它:The LoadFromXaml method can be used to inflate any XAML, with the following example inflating a ContentPage and then navigating to it:

using Xamarin.Forms.Xaml;
...

// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n</ContentPage>";

ContentPage page = new ContentPage().LoadFromXaml(pageXAML);
await Navigation.PushAsync(page);

存取元素Accessing elements

使用LoadFromXaml方法在執行時間載入 xaml 時,不允許具有指定執行時間物件名稱(使用 x:Name)之 xaml 元素的強型別存取。Loading XAML at runtime with the LoadFromXaml method does not permit strongly-typed access to the XAML elements that have specified runtime object names (using x:Name). 不過,您可以使用FindByName方法來抓取這些 XAML 元素,然後視需要存取:However, these XAML elements can be retrieved using the FindByName method, and then accessed as required:

// See the sample for the full XAML string
string pageXAML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\nxmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\nx:Class=\"LoadRuntimeXAML.CatalogItemsPage\"\nTitle=\"Catalog Items\">\n<StackLayout>\n<Label x:Name=\"monkeyName\"\n />\n</StackLayout>\n</ContentPage>";
ContentPage page = new ContentPage().LoadFromXaml(pageXAML);

Label monkeyLabel = page.FindByName<Label>("monkeyName");
monkeyLabel.Text = "Seated Monkey";
...

在此範例中, ContentPage的 XAML 已膨脹。In this example, the XAML for a ContentPage is inflated. 此 XAML 包含名為 monkeyNameLabel ,它會使用FindByName方法來抓取,然後才設定其Text屬性。This XAML includes a Label named monkeyName, which is retrieved using the FindByName method, before its Text property is set.