Multi binding di Xamarin.Forms

Download Sample Scaricare l'esempio

Le associazioni multi-binding consentono di associare una raccolta di Binding oggetti a una singola proprietà di destinazione di associazione. Vengono creati con la MultiBinding classe , che valuta tutti i relativi Binding oggetti e restituisce un singolo valore tramite un'istanza IMultiValueConverter fornita dall'applicazione. Inoltre, MultiBinding rivaluta tutti i relativi Binding oggetti quando uno dei dati associati cambia.

La MultiBinding classe definisce le proprietà seguenti:

  • Bindings, di tipo IList<BindingBase>, che rappresenta la raccolta di Binding oggetti all'interno dell'istanza MultiBinding di .
  • Converter, di tipo IMultiValueConverter, che rappresenta il convertitore da utilizzare per convertire i valori di origine in o dal valore di destinazione.
  • ConverterParameter, di tipo object, che rappresenta un parametro facoltativo da passare a Converter.

La Bindings proprietà è la proprietà content della MultiBinding classe e pertanto non deve essere impostata in modo esplicito da XAML.

Inoltre, la MultiBinding classe eredita le proprietà seguenti dalla BindingBase classe :

  • FallbackValue, di tipo object, che rappresenta il valore da utilizzare quando l'associazione multipla non è in grado di restituire un valore.
  • Mode, di tipo BindingMode, che indica la direzione del flusso di dati dell'associazione multipla.
  • StringFormat, di tipo string, che specifica come formattare il risultato dell'associazione multipla se viene visualizzato come stringa.
  • TargetNullValue, di tipo object, che rappresenta il valore usato nella destinazione wen il valore dell'origine è null.

Un MultiBinding oggetto deve utilizzare un IMultiValueConverter oggetto per produrre un valore per la destinazione di associazione, in base al valore delle associazioni nella Bindings raccolta. Ad esempio, un Color può essere calcolato da valori di origine rosso, blu e verde, che possono essere valori degli stessi oggetti di origine di associazione o diversi. Quando un valore passa dalla destinazione alle origini, il valore della proprietà di destinazione viene convertito in un set di valori che vengono reinseriti nelle associazioni.

Importante

I singoli binding nella Bindings raccolta possono avere convertitori di valori personalizzati.

Il valore della Mode proprietà determina la funzionalità di MultiBindinge viene utilizzato come modalità di associazione per tutte le associazioni dell'insieme, a meno che una singola associazione non esegua l'override della proprietà. Ad esempio, se la Mode proprietà di un MultiBinding oggetto è impostata su TwoWay, tutte le associazioni nell'insieme vengono considerate TwoWay a meno che non si imposti in modo esplicito un valore diverso Mode su una delle associazioni.

Definire un oggetto IMultiValueConverter

L'interfaccia IMultiValueConverter consente di applicare la logica personalizzata a un oggetto MultiBinding. Per associare un convertitore a un MultiBindingoggetto , creare una classe che implementa l'interfaccia IMultiValueConverter e quindi implementare i Convert metodi e 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;
        }
    }
}

Il Convert metodo converte i valori di origine in un valore per la destinazione dell'associazione. Xamarin.Forms chiama questo metodo quando propaga i valori dalle associazioni di origine alla destinazione dell'associazione. Questo metodo accetta quattro argomenti:

  • values, di tipo object[], è una matrice di valori prodotti dalle associazioni di origine nell'oggetto MultiBinding .
  • targetType, di tipo Type, è il tipo della proprietà di destinazione dell'associazione.
  • parameter, di tipo object, è il parametro del convertitore da usare.
  • culture, di tipo CultureInfo, è le impostazioni cultura da usare nel convertitore.

Il Convert metodo restituisce un oggetto object che rappresenta un valore convertito. Questo metodo deve restituire:

  • BindableProperty.UnsetValueper indicare che il convertitore non ha prodotto un valore e che l'associazione userà .FallbackValue
  • Binding.DoNothing per indicare a Xamarin.Forms di non eseguire alcuna azione. Ad esempio, per indicare a Xamarin.Forms di non trasferire un valore alla destinazione di associazione o di non usare .FallbackValue
  • nullper indicare che il convertitore non può eseguire la conversione e che l'associazione userà .TargetNullValue

Importante

Oggetto MultiBinding che riceve BindableProperty.UnsetValue da un Convert metodo deve definire la relativa FallbackValue proprietà. Analogamente, un oggetto MultiBinding che riceve null da un Convert metodo deve definirne la TargetNullValue proprietà.

Il ConvertBack metodo converte una destinazione di associazione nei valori di associazione di origine. Questo metodo accetta quattro argomenti:

  • value, di tipo object, è il valore prodotto dalla destinazione di associazione.
  • targetTypes, di tipo Type[], è la matrice di tipi in cui eseguire la conversione. La lunghezza della matrice indica il numero e i tipi di valori proposti per la restituzione da parte del metodo.
  • parameter, di tipo object, è il parametro del convertitore da usare.
  • culture, di tipo CultureInfo, è le impostazioni cultura da usare nel convertitore.

Il ConvertBack metodo restituisce una matrice di valori, di tipo object[], che sono stati convertiti dal valore di destinazione ai valori di origine. Questo metodo deve restituire:

  • BindableProperty.UnsetValue in posizione i per indicare che il convertitore non è in grado di fornire un valore per l'associazione di origine in corrispondenza dell'indice ie che non deve essere impostato alcun valore su di esso.
  • Binding.DoNothing in posizione i per indicare che non deve essere impostato alcun valore nell'associazione di origine in corrispondenza dell'indice i.
  • null per indicare che il convertitore non può eseguire la conversione o che non supporta la conversione in questa direzione.

Utilizzare un oggetto IMultiValueConverter

Un IMultiValueConverter oggetto viene utilizzato creando un'istanza in un dizionario risorse e quindi facendo riferimento a esso usando l'estensione StaticResource di markup per impostare la MultiBinding.Converter proprietà :

<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>    

In questo esempio l'oggetto usa l'istanza AllTrueMultiConverter di per impostare la CheckBox.IsChecked proprietà su true, a condizione che i tre Binding oggetti restituiscono true.MultiBinding In caso contrario, la CheckBox.IsChecked proprietà è impostata su false.

Per impostazione predefinita, la CheckBox.IsChecked proprietà usa un'associazione TwoWay . Di conseguenza, il ConvertBack metodo dell'istanza AllTrueMultiConverter viene eseguito quando l'oggetto CheckBox viene deselezionato dall'utente, che imposta i valori dell'associazione di origine sul valore della CheckBox.IsChecked proprietà.

Il codice C# equivalente è illustrato di seguito:

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;
    }
}

Stringhe di formato

Un MultiBinding oggetto può formattare qualsiasi risultato di associazione multipla visualizzato come stringa, con la StringFormat proprietà . Questa proprietà può essere impostata su una stringa di formattazione .NET standard, con segnaposto, che specifica come formattare il risultato dell'associazione multipla:

<Label>
    <Label.Text>
        <MultiBinding StringFormat="{}{0} {1} {2}">
            <Binding Path="Employee1.Forename" />
            <Binding Path="Employee1.MiddleName" />
            <Binding Path="Employee1.Surname" />
        </MultiBinding>
    </Label.Text>
</Label>

In questo esempio la StringFormat proprietà combina i tre valori associati in una singola stringa visualizzata da Label.

Il codice C# equivalente è illustrato di seguito:

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}"
});

Importante

Il numero di parametri in un formato di stringa composita non può superare il numero di oggetti figlio Binding in MultiBinding.

Quando si impostano le Converter proprietà eStringFormat, il convertitore viene applicato prima al valore di dati e quindi viene applicato .StringFormat

Per altre informazioni sulla formattazione delle stringhe in Xamarin.Forms, vedere Formattazione di stringhe Xamarin.Forms.

Specificare i valori di fallback

I data binding possono essere resi più affidabili definendo i valori di fallback da usare se il processo di associazione ha esito negativo. Questa operazione può essere eseguita definendo facoltativamente le FallbackValue proprietà e TargetNullValue in un MultiBinding oggetto .

Un MultiBinding oggetto userà FallbackValue quando il Convert metodo di un'istanza IMultiValueConverter restituisce BindableProperty.UnsetValue, che indica che il convertitore non ha prodotto un valore. Un MultiBinding oggetto userà TargetNullValue quando il Convert metodo di un'istanza IMultiValueConverter restituisce null, che indica che il convertitore non può eseguire la conversione.

Per altre informazioni sui fallback di binding, vedere Fallback di binding di Xamarin.Forms.

Annidare oggetti MultiBinding

MultiBinding Gli oggetti possono essere annidati in modo che più MultiBinding oggetti vengano valutati per restituire un valore tramite un'istanza IMultiValueConverter di :

<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>

In questo esempio, l'oggetto MultiBinding usa la relativa AnyTrueMultiConverter istanza per impostare la CheckBox.IsChecked proprietà su true, a condizione che tutti gli Binding oggetti dell'oggetto interno MultiBinding restituiscono trueo che l'oggetto Binding nell'oggetto esterno MultiBinding restituisca true. In caso contrario, la CheckBox.IsChecked proprietà è impostata su false.

Usare un'associazione RelativeSource in un multibinding

MultiBinding gli oggetti supportano associazioni relative, che consentono di impostare l'origine dell'associazione in relazione alla posizione della destinazione dell'associazione:

<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>

Nota

Il Expander controllo fa ora parte di Xamarin Community Toolkit.

In questo esempio viene usata la TemplatedParent modalità di associazione relativa per eseguire il binding dall'interno di un modello di controllo all'istanza dell'oggetto di runtime a cui viene applicato il modello. L'oggetto Expander, che è l'elemento radice di , ha il relativo BindingContext set sull'istanza dell'oggetto ControlTemplateruntime a cui viene applicato il modello. Pertanto, gli oggetti e i Expander relativi elementi figlio risolvono le espressioni di associazione e Binding gli oggetti rispetto alle proprietà dell'oggetto CardViewExpander . MultiBinding Usa l'istanza AllTrueMultiConverter di per impostare la Expander.IsVisible proprietà su a true condizione che i due Binding oggetti restituiscono true. In caso contrario, la Expander.IsVisible proprietà è impostata su false.

Per altre informazioni sulle associazioni relative, vedere Associazioni relative di Xamarin.Forms. Per altre informazioni sui modelli di controllo, vedere Modelli di controllo Xamarin.Forms.