Xamarin.Forms 系結路徑
在所有先前的資料繫結範例中,Binding
類別的 Path
屬性 (或 Binding
標記延伸模組的 Path
屬性) 已設成單一屬性。 將 Path
設成「子屬性」(屬性的屬性) 或集合成員實際上是可行的。
例如,假設您的頁面包含 TimePicker
:
<TimePicker x:Name="timePicker">
TimePicker
的 Time
屬性類別為 TimeSpan
,但您可能想要建立資料繫結,參考該 TimeSpan
值的 TotalSeconds
屬性。 以下是資料繫結:
{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds}
Time
屬性的類型為 TimeSpan
,其具有 TotalSeconds
屬性。 Time
和 TotalSeconds
屬性只簡單使用句號連接。 Path
字串中的項目一律表示屬性,且不是這些屬性的類型。
[Path Variations] \(路徑變化\) 頁面會顯示該範例及其他許多範例:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:globe="clr-namespace:System.Globalization;assembly=netstandard"
x:Class="DataBindingDemos.PathVariationsPage"
Title="Path Variations"
x:Name="page">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10, 0">
<TimePicker x:Name="timePicker" />
<Label Text="{Binding Source={x:Reference timePicker},
Path=Time.TotalSeconds,
StringFormat='{0} total seconds'}" />
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children.Count,
StringFormat='There are {0} children in this StackLayout'}" />
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The second Label has {0} characters'}" />
</StackLayout>
</ContentPage>
在第二個 Label
中,繫結來源是網頁本身。 Content
屬性的類型為 StackLayout
,其 Children
屬性的類型為 IList<View>
,它又包含指示子系數目的 Count
屬性。
具有索引子的路徑
[Path Variations] \(路徑變化\) 頁面中第三個 Label
的繫結會參考 System.Globalization
命名空間中的 CultureInfo
類別:
<Label Text="{Binding Source={x:Static globe:CultureInfo.CurrentCulture},
Path=DateTimeFormat.DayNames[3],
StringFormat='The middle day of the week is {0}'}" />
來源設為靜態的 CultureInfo.CurrentCulture
屬性,其為類型 CultureInfo
的物件。 類別定義的屬性名為 DateTimeFormat
,其類型為包含 DayNames
集合的 DateTimeFormatInfo
。 索引會選取第四個項目。
第四個 Label
作用類似,但適用於與法國建立關聯的文化特性。 繫結的 Source
屬性設為具有建構函式的 CultureInfo
物件:
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
如需在 XAML 中指定建構函式引數的詳細資料,請參閱傳遞建構函式引數。
最後,最後一個範例類似第二個,不同之處在於它參考的是 StackLayout
子系的其中之一:
<Label Text="{Binding Source={x:Reference page},
Path=Content.Children[1].Text.Length,
StringFormat='The first Label has {0} characters'}" />
該子系為 Label
,其 Text
屬性的類型為包含 Length
屬性的 String
。 第一個 Label
回報 TimePicker
中設定的 TimeSpan
,所以當該文字變更時,最終的 Label
也跟著變更。
以下是程式執行情況:
偵錯複雜路徑
複雜的路徑定義建構困難:您需要知道每個子屬性的類型或集合項目的類型,才能正確新增下一個子屬性,但類型本身不會出現在路徑中。 一個良好技巧是以累加方式建置的路徑,並查看中繼結果。 至於最後一個範例,您完全可以從沒有 Path
定義開始:
<Label Text="{Binding Source={x:Reference page},
StringFormat='{0}'}" />
它會顯示繫結來源屬性類型或 DataBindingDemos.PathVariationsPage
。 您知道 PathVariationsPage
衍生自 ContentPage
,所以它有 Content
屬性:
<Label Text="{Binding Source={x:Reference page},
Path=Content,
StringFormat='{0}'}" />
Content
屬性的類型現顯示為 Xamarin.Forms.StackLayout
。 將 Children
屬性新增至 Path
,而類型為 Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View]
,這是內部的 Xamarin.Forms類別,但顯然是集合類型。 將索引新增至該範例,且類型為 Xamarin.Forms.Label
。 繼續以這種方式進行。
當 Xamarin.Forms 處理系結路徑時,它會 PropertyChanged
在實 INotifyPropertyChanged
作 介面的路徑中的任何對象上安裝處理程式。 例如,因為 Text
屬性變更,所以最後一個繫結回應第一個 Label
中的變更。
如果繫結路徑中的屬性不實作 INotifyPropertyChanged
,則忽略該屬性的所有變更。 某些變更可能會讓繫結路徑完全失效,所以您只有在屬性和子屬性的字串還未失效前,才使用這項技術。