Compartilhar via


Multiligações Xamarin.Forms

As multiligações fornecem a capacidade de anexar uma coleção de objetos a uma única propriedade de destino de Binding vinculação. Eles são criados com a classe, que avalia MultiBinding todos os seus Binding objetos e retorna um único valor por meio de uma IMultiValueConverter instância fornecida pelo seu aplicativo. Além disso, MultiBinding reavalia todos os seus Binding objetos quando qualquer um dos dados vinculados é alterado.

A classe MultiBinding define as seguintes propriedades:

  • Bindings, do tipo IList<BindingBase>, que representa a coleção de Binding objetos dentro da MultiBinding instância.
  • Converter, do tipo IMultiValueConverter, que representa o conversor a ser usado para converter os valores de origem de ou para o valor de destino.
  • ConverterParameter, do tipo object, que representa um parâmetro opcional a ser passado para o Converter.

A propriedade Bindings é a propriedade de conteúdo da classe MultiBinding e, portanto, não precisa ser definida explicitamente no XAML.

Além disso, a MultiBinding classe herda as seguintes propriedades da BindingBase classe:

  • FallbackValue, do tipo object, que representa o valor a ser usado quando a multivinculação não puder retornar um valor.
  • Mode, do tipo BindingMode, que indica a direção do fluxo de dados da ligação múltipla.
  • StringFormat, do tipo string, que especifica como formatar o resultado de várias vinculações se ele for exibido como uma cadeia de caracteres.
  • TargetNullValue, do tipo object, que representa o valor que é usado no destino wen o valor da origem é null.

A MultiBinding deve usar a IMultiValueConverter para produzir um valor para o destino de vinculação, com base no valor das ligações na Bindings coleção. Por exemplo, a Color pode ser calculado a partir de valores vermelhos, azuis e verdes, que podem ser valores do mesmo objeto de origem de vinculação ou de objetos de origem diferentes. Quando um valor se move do destino para as origens, o valor da propriedade de destino é convertido em um conjunto de valores que são alimentados de volta para as associações.

Importante

Ligações individuais na Bindings coleção podem ter seus próprios conversores de valor.

O valor da Mode propriedade determina a funcionalidade do , e é usado como o modo de MultiBindingvinculação para todas as associações na coleção, a menos que uma associação individual substitua a propriedade. Por exemplo, se a Mode propriedade em um MultiBinding objeto estiver definida como TwoWay, todas as associações na coleção serão consideradas TwoWay , a menos que você defina explicitamente um valor diferente Mode em uma das associações.

Definir um IMultiValueConverter

A IMultiValueConverter interface permite que a lógica personalizada seja aplicada a um MultiBindingarquivo . Para associar um conversor a um MultiBinding, crie uma classe que implemente a IMultiValueConverter interface e, em seguida, implemente os Convert métodos 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;
        }
    }
}

O Convert método converte valores de origem em um valor para o destino de vinculação. Xamarin.Forms chama esse método quando ele propaga valores de associações de origem para o destino de vinculação. Esse método aceita quatro argumentos:

  • values, do tipo object[], é uma matriz de valores que a fonte vincula no MultiBinding produz.
  • targetType, do tipo Type, é o tipo da propriedade de destino de vinculação.
  • parameter, do tipo object, é o parâmetro conversor a ser usado.
  • culture, do tipo CultureInfo, é a cultura a ser usada no conversor.

O Convert método retorna um object que representa um valor convertido. Esse método deve retornar:

  • BindableProperty.UnsetValue para indicar que o conversor não produziu um valor e que a vinculação usará o FallbackValue.
  • Binding.DoNothing para instruir o Xamarin.Forms a não executar nenhuma ação. Por exemplo, para instruir o Xamarin.Forms a não transferir um valor para o destino de vinculação ou a não usar o FallbackValue.
  • null para indicar que o conversor não pode executar a conversão e que a associação usará o TargetNullValue.

Importante

Um MultiBinding que recebe BindableProperty.UnsetValue de um Convert método deve definir sua FallbackValue propriedade. Da mesma forma, um MultiBinding que recebe null de um Convert método deve definir sua TargetNullValue propriedade.

O ConvertBack método converte um destino de vinculação para os valores de vinculação de origem. Esse método aceita quatro argumentos:

  • value, do tipo object, é o valor que o destino de vinculação produz.
  • targetTypes, do tipo Type[], é a matriz de tipos para a qual converter. O comprimento da matriz indica o número e tipos de valores sugeridos para o método retornar.
  • parameter, do tipo object, é o parâmetro conversor a ser usado.
  • culture, do tipo CultureInfo, é a cultura a ser usada no conversor.

O ConvertBack método retorna uma matriz de valores, do tipo object[], que foram convertidos do valor de destino de volta para os valores de origem. Esse método deve retornar:

  • BindableProperty.UnsetValue na posição i para indicar que o conversor não consegue fornecer um valor para a ligação de origem no índice i, e que nenhum valor deve ser definido nele.
  • Binding.DoNothing na posição i para indicar que nenhum valor deve ser definido na vinculação de origem no índice i.
  • null para indicar que o conversor não pode executar a conversão ou que ele não oferece suporte à conversão nessa direção.

Consumir um IMultiValueConverter

A IMultiValueConverter é consumido instanciando-o em um dicionário de recursos e, em seguida, referenciando-o usando a extensão de StaticResource marcação para definir a MultiBinding.Converter propriedade:

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

Neste exemplo, o MultiBinding objeto usa a AllTrueMultiConverter instância para definir a CheckBox.IsChecked propriedade como true, desde que os três Binding objetos avaliem como true. Caso contrário, a CheckBox.IsChecked propriedade será definida como false.

Por padrão, a CheckBox.IsChecked propriedade usa uma TwoWay associação. Portanto, o ConvertBackAllTrueMultiConverter método da instância é executado quando o CheckBox é desmarcado pelo usuário, que define os valores de vinculação de origem para o CheckBox.IsChecked valor da propriedade.

O código C# equivalente é mostrado abaixo:

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

Cadeias de caracteres de formato

Um MultiBinding pode formatar qualquer resultado de multivinculação que é exibido como uma cadeia de caracteres, com a StringFormat propriedade. Essa propriedade pode ser definida como uma cadeia de caracteres de formatação .NET padrão, com espaços reservados, que especifica como formatar o resultado de várias vinculações:

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

Neste exemplo, a StringFormat propriedade combina os três valores vinculados em uma única cadeia de caracteres exibida pelo Label.

O código C# equivalente é mostrado abaixo:

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

O número de parâmetros em um formato de cadeia de caracteres composto não pode exceder o número de objetos filho Binding no MultiBinding.

Ao definir as Converter propriedades e StringFormat , o conversor é aplicado ao valor de dados primeiro e, em seguida, o StringFormat é aplicado.

Para obter mais informações sobre formatação de cadeia de caracteres no Xamarin.Forms, consulte Xamarin.Forms String Formatting.

Fornecer valores de fallback

As associações de dados podem ser tornadas mais robustas definindo valores de fallback a serem usados se o processo de vinculação falhar. Isso pode ser feito definindo opcionalmente as FallbackValue propriedades e TargetNullValue em um MultiBinding objeto.

A MultiBinding usará seu FallbackValue quando o Convert método de uma IMultiValueConverter instância retornar BindableProperty.UnsetValue, o que indica que o conversor não produziu um valor. A MultiBinding usará seu TargetNullValue quando o Convert método de uma IMultiValueConverter instância retornar null, o que indica que o conversor não pode executar a conversão.

Para obter mais informações sobre fallbacks de vinculação, consulte Xamarin.Forms Binding Fallbacks.

Aninhar objetos MultiBinding

MultiBinding Os objetos podem ser aninhados para que vários MultiBinding objetos sejam avaliados para retornar um valor por meio de uma IMultiValueConverter instância:

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

Neste exemplo, o MultiBinding objeto usa sua AnyTrueMultiConverter instância para definir a CheckBox.IsChecked propriedade como true, desde que todos os Binding objetos no objeto interno MultiBinding sejam avaliados como true, ou desde que o Binding objeto no objeto externo MultiBinding seja avaliado como true. Caso contrário, a CheckBox.IsChecked propriedade será definida como false.

Usar uma associação RelativeSource em um MultiBinding

MultiBinding Os objetos oferecem suporte a ligações relativas, que fornecem a capacidade de definir a origem da vinculação em relação à posição do destino da vinculação:

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

Observação

O Expander controle agora faz parte do Xamarin Community Toolkit.

Neste exemplo, o TemplatedParent modo de vinculação relativa é usado para vincular de dentro de um modelo de controle à instância do objeto de tempo de execução à qual o modelo é aplicado. O Expander, que é o elemento raiz do , tem seu BindingContext conjunto para a instância do objeto de tempo de ControlTemplateexecução à qual o modelo é aplicado. Portanto, o e seus filhos resolvem Expander suas expressões de ligação, e Binding objetos, contra as propriedades do CardViewExpander objeto. O MultiBinding usa a AllTrueMultiConverter instância para definir a Expander.IsVisible propriedade como true desde que os dois Binding objetos avaliem como true. Caso contrário, a Expander.IsVisible propriedade será definida como false.

Para obter mais informações sobre associações relativas, veja Associações Relativas do Xamarin.Forms. Para obter mais informações sobre modelos de controle, consulte Modelos de controle Xamarin.Forms.