多重系結可讓您將 物件的集合 Binding 附加至單一系結目標屬性。 它們會使用 MultiBinding 類別來建立,其會評估其 Binding 所有物件,並透過 IMultiValueConverter 應用程式提供的實例傳回單一值。 此外,當任何系結的數據變更時, MultiBinding 會重新評估其 Binding 所有物件。
類別 MultiBinding 會定義下列屬性:
Bindings型IList<BindingBase>別為 的 ,表示 實例內的MultiBinding物件集合Binding。Converter型IMultiValueConverter別為 的 ,表示用來將來源值轉換為目標值或從目標值轉換的轉換子。ConverterParameter型object別為 的 ,表示要傳遞至 的Converter選擇性參數。
屬性 Bindings 是 類別的內容屬性 MultiBinding ,因此不需要從 XAML 明確設定。
此外,類別 MultiBinding 會從 BindingBase 類別繼承下列屬性:
FallbackValue型object別為 的 ,表示當多重系結無法傳回值時要使用的值。Mode型BindingMode別為 ,表示多重系結數據流的方向。StringFormat型string別為 的 ,指定當多重系結結果顯示為字串時,如何格式化。TargetNullValue型object別為 ,表示目標中使用的值,溫來源的值為null。
MultiBinding必須使用 IMultiValueConverter ,根據集合中的Bindings系結值,為系結目標產生值。 例如, Color 可能會從紅色、藍色和綠色值計算,這些值可以是來自相同或不同系結來源物件的值。 當值從目標移至來源時,目標屬性值會轉譯成一組傳回系結的值。
重要
集合中的 Bindings 個別系結可以有自己的值轉換器。
屬性的值 Mode 會決定 的功能 MultiBinding,除非個別系結覆寫 屬性,否則會當做集合中所有系結的系結模式使用。 例如,如果 Mode 物件上的 MultiBinding 屬性設定為 TwoWay,則除非您在其中一個系結上明確設定不同的Mode值,否則會考慮TwoWay集合中的所有系結。
定義 IMultiValueConverter
介面 IMultiValueConverter 可讓自訂邏輯套用至 MultiBinding。 若要將轉換器與 MultiBinding產生關聯,請建立實作 介面的 IMultiValueConverter 類別,然後實 Convert 作 和 ConvertBack 方法:
public class AllTrueMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || !targetType.IsAssignableFrom(typeof(bool)))
{
return false;
// Alternatively, return BindableProperty.UnsetValue to use the binding FallbackValue
}
foreach (var value in values)
{
if (!(value is bool b))
{
return false;
// Alternatively, return BindableProperty.UnsetValue to use the binding FallbackValue
}
else if (!b)
{
return false;
}
}
return true;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
if (!(value is bool b) || targetTypes.Any(t => !t.IsAssignableFrom(typeof(bool))))
{
// Return null to indicate conversion back is not possible
return null;
}
if (b)
{
return targetTypes.Select(t => (object)true).ToArray();
}
else
{
// Can't convert back from false because of ambiguity
return null;
}
}
}
方法 Convert 會將來源值轉換成系結目標的值。 Xamarin.Forms 會在將值從來源系結傳播至系結目標時,呼叫這個方法。 此方法接受四個自變數:
values型object[]別為 的 ,是 中來源系結MultiBinding所產生的值陣列。targetType型Type別為 的 ,是系結目標屬性的類型。parameter類型object為 的 ,是要使用的轉換器參數。culture型CultureInfo別為 的 ,是轉換子中使用的文化特性。
方法會Convertobject傳回 ,表示已轉換的值。 此方法應該會傳回:
BindableProperty.UnsetValue表示轉換子未產生值,而且系結將使用FallbackValue。Binding.DoNothing指示 Xamarin.Forms 不要執行任何動作。 例如,若要指示 Xamarin.Forms 不要將值傳送至系結目標,或不要使用FallbackValue。null表示轉換子無法執行轉換,而且系結將使用TargetNullValue。
重要
MultiBinding從方法接收BindableProperty.UnsetValue的 Convert ,必須定義其 FallbackValue 屬性。 同樣地, MultiBinding 從方法接收 null 的 Convert 必須定義其 TargetNullValue propety。
方法 ConvertBack 會將系結目標轉換為來源系結值。 此方法接受四個自變數:
value型object別為 的 ,是系結目標所產生的值。targetTypes型Type[]別為 的 ,是要轉換成的類型數位。 陣列長度表示方法要傳回之建議值的數目和類型。parameter類型object為 的 ,是要使用的轉換器參數。culture型CultureInfo別為 的 ,是轉換子中使用的文化特性。
方法 ConvertBack 會傳回類型 object[]為的值陣列,其已從目標值轉換回來源值。 此方法應該會傳回:
BindableProperty.UnsetValue位於i,表示轉換子無法在索引i上提供來源系結的值,而且不會設定任何值。Binding.DoNothing在 位置i,表示在索引i的來源系結上不會設定任何值。null表示轉換子無法執行轉換,或不支援以這個方向進行轉換。
取用 IMultiValueConverter
IMultiValueConverter藉由在資源字典中具現化它,然後使用標記延伸來參考它,以設定 MultiBinding.Converter 屬性來取用StaticResource它:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.MultiBindingConverterPage"
Title="MultiBinding Converter demo">
<ContentPage.Resources>
<local:AllTrueMultiConverter x:Key="AllTrueConverter" />
<local:InverterConverter x:Key="InverterConverter" />
</ContentPage.Resources>
<CheckBox>
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource AllTrueConverter}">
<Binding Path="Employee.IsOver16" />
<Binding Path="Employee.HasPassedTest" />
<Binding Path="Employee.IsSuspended"
Converter="{StaticResource InverterConverter}" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</ContentPage>
在這裡範例中 MultiBinding ,物件會 AllTrueMultiConverter 使用 實體將 屬性設定 CheckBox.IsChecked 為 true,前提是這三 Binding 個物件評估為 true。 否則,屬性 CheckBox.IsChecked 會設定為 false。
根據預設, CheckBox.IsChecked 屬性會使用系 TwoWay 結。 因此,ConvertBack當使用者取消核取 時CheckBox,會執行 實例的 AllTrueMultiConverter 方法,這會將來源系結值設定為 屬性的值CheckBox.IsChecked。
對等的 C# 程式代碼如下所示:
public class MultiBindingConverterCodePage : ContentPage
{
public MultiBindingConverterCodePage()
{
BindingContext = new GroupViewModel();
CheckBox checkBox = new CheckBox();
checkBox.SetBinding(CheckBox.IsCheckedProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding("Employee1.IsOver16"),
new Binding("Employee1.HasPassedTest"),
new Binding("Employee1.IsSuspended", converter: new InverterConverter())
},
Converter = new AllTrueMultiConverter()
});
Title = "MultiBinding converter demo";
Content = checkBox;
}
}
格式字串
MultiBinding可以使用 屬性來格式化顯示為字串StringFormat的任何多重系結結果。 這個屬性可以設定為標準 .NET 格式字串,並具有佔位元,指定如何格式化多重系結結果:
<Label>
<Label.Text>
<MultiBinding StringFormat="{}{0} {1} {2}">
<Binding Path="Employee1.Forename" />
<Binding Path="Employee1.MiddleName" />
<Binding Path="Employee1.Surname" />
</MultiBinding>
</Label.Text>
</Label>
在此範例中 StringFormat ,屬性會將這三個系結值結合成 由 Label顯示的單一字串。
對等的 C# 程式代碼如下所示:
Label label = new Label();
label.SetBinding(Label.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding("Employee1.Forename"),
new Binding("Employee1.MiddleName"),
new Binding("Employee1.Surname")
},
StringFormat = "{0} {1} {2}"
});
重要
複合字串格式中的參數數目不能超過 中的MultiBinding子Binding物件數目。
設定 Converter 與 StringFormat 屬性時,轉換器會先套用至資料值,然後 StringFormat 套用 。
如需 Xamarin.Forms 中字串格式設定的詳細資訊,請參閱 Xamarin.Forms 字串格式設定。
提供後援值
定義系結程序失敗時要使用的後援值,即可讓數據系結更加健全。 這可藉由選擇性地定義 FallbackValue 物件上的 MultiBinding 和 TargetNullValue 屬性來完成。
MultiBinding當實例的 IMultiValueConverter 方法傳回 BindableProperty.UnsetValue時Convert,會使用 ,FallbackValue表示轉換子未產生值。 MultiBinding當實例的 IMultiValueConverter 方法傳回 null時Convert,會使用 ,TargetNullValue表示轉換子無法執行轉換。
如需系結後援的詳細資訊,請參閱 Xamarin.Forms 系結後援。
巢狀 MultiBinding 物件
MultiBinding 物件可以巢狀化,以便評估多個 MultiBinding 物件,以透過 IMultiValueConverter 實例傳回值:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.NestedMultiBindingPage"
Title="Nested MultiBinding demo">
<ContentPage.Resources>
<local:AllTrueMultiConverter x:Key="AllTrueConverter" />
<local:AnyTrueMultiConverter x:Key="AnyTrueConverter" />
<local:InverterConverter x:Key="InverterConverter" />
</ContentPage.Resources>
<CheckBox>
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource AnyTrueConverter}">
<MultiBinding Converter="{StaticResource AllTrueConverter}">
<Binding Path="Employee.IsOver16" />
<Binding Path="Employee.HasPassedTest" />
<Binding Path="Employee.IsSuspended" Converter="{StaticResource InverterConverter}" />
</MultiBinding>
<Binding Path="Employee.IsMonarch" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</ContentPage>
在這裡範例中MultiBinding,物件會使用 其 AnyTrueMultiConverter 實體將 屬性設定CheckBox.IsChecked為 true,前提是內部MultiBinding物件中的所有Binding物件都評估為 true,或前提是Binding外部MultiBinding物件中的物件評估為 true。 否則,屬性 CheckBox.IsChecked 會設定為 false。
在 MultiBinding 中使用 RelativeSource 系結
MultiBinding 物件支持相對系結,可提供設定系結來源相對於系結目標位置的能力:
<ContentPage ...
xmlns:local="clr-namespace:DataBindingDemos"
xmlns:xct="clr-namespace:Xamarin.CommunityToolkit.UI.Views;assembly=Xamarin.CommunityToolkit">
<ContentPage.Resources>
<local:AllTrueMultiConverter x:Key="AllTrueConverter" />
<ControlTemplate x:Key="CardViewExpanderControlTemplate">
<xct:Expander BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
IsExpanded="{Binding IsExpanded, Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}">
<xct:Expander.IsVisible>
<MultiBinding Converter="{StaticResource AllTrueConverter}">
<Binding Path="IsExpanded" />
<Binding Path="IsEnabled" />
</MultiBinding>
</xct:Expander.IsVisible>
<xct:Expander.Header>
<Grid>
<!-- XAML that defines Expander header goes here -->
</Grid>
</xct:Expander.Header>
<Grid>
<!-- XAML that defines Expander content goes here -->
</Grid>
</xct:Expander>
</ControlTemplate>
</ContentPage.Resources>
<StackLayout>
<controls:CardViewExpander BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewExpanderControlTemplate}"
IsEnabled="True"
IsExpanded="True" />
</StackLayout>
</ContentPage>
注意
控件 Expander 現在是 Xamarin Community Toolkit 的一部分。
在此範例中,會使用相對系 TemplatedParent 結模式,從控件範本內系結至套用範本的運行時間物件實例。 Expander,這是的ControlTemplate根元素,其BindingContext已設定為套用範本的運行時間對象實例。 因此,Expander及其子系會針對 對象的屬性CardViewExpander解析其系結表達式和 Binding 物件。 MultiBinding會AllTrueMultiConverter使用 實體來設定 Expander.IsVisible 屬性,true前提是兩Binding個物件評估為 true。 否則,屬性 Expander.IsVisible 會設定為 false。
如需相對繫結的詳細資訊,請參閱 Xamarin.Forms 相對繫結。 如需控件範本的詳細資訊,請參閱 Xamarin.Forms 控件範本。