Xamarin.Forms Převaděče hodnot vazeb

Stáhnout ukázku Stažení ukázky

Datové vazby obvykle přenesou data ze zdrojové vlastnosti do cílové vlastnosti a v některých případech z cílové vlastnosti do zdrojové vlastnosti. Tento přenos je jednoduchý, pokud jsou vlastnosti zdroje a cíle stejného typu nebo když jeden typ lze převést na druhý typ prostřednictvím implicitního převodu. Pokud tomu tak není, musí se provést převod typu.

V článku Formátování řetězců jste viděli, jak můžete pomocí vlastnosti datové vazby převést libovolný typ na řetězec. Pro jiné typy převodů je nutné napsat nějaký specializovaný kód ve třídě, která implementuje IValueConverter rozhraní. (Univerzální platforma Windows obsahuje podobnou třídu s názvem v oboru názvů IValueConverter , ale je v oboru názvů Windows.UI.Xaml.DataIValueConverterXamarin.Forms .) Třídy, které implementují , se nazývají převaděče hodnot , ale často se označují také jako převaděče vazeb nebo IValueConverterpřevaděče hodnot vazebIValueConverter.

Rozhraní IValueConverter

Předpokládejme, že chcete definovat datovou vazbu, ve které je zdrojová vlastnost typu int , ale cílovou vlastností je bool . Chcete, aby tato datová vazba vyprodukuje hodnotu, pokud se celočíselný zdroj false rovná 0 a true jinak.

Můžete to provést pomocí třídy, která implementuje IValueConverter rozhraní:

public class IntToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value != 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? 1 : 0;
    }
}

Instanci této třídy nastavíte na _Binding_Converter" data-linktype="absolute-path">třídy nebo na vlastnost Converter Xamarin_Forms BindingConverter _Xaml_BindingExtension_Converter" data-linktype="absolute-path">rozšíření ConverterBinding značek. Tato třída se stává součástí datové vazby.

Metoda Convert je volána při přesunu dat ze zdroje do cíle ve OneWayTwoWay vazbách nebo . Parametr value je objekt nebo hodnota ze zdroje datových vazeb. Metoda musí vracet hodnotu typu cíle datové vazby. Zde zobrazená metoda přetypuje parametr na a pak ho porovnává s valueint hodnotou 0 pro bool návratovou hodnotu.

Metoda ConvertBack je volána při přesunu dat z cíle do zdroje v nebo TwoWayOneWayToSource vazby. ConvertBack provede opačný převod: Předpokládá, že parametr je z cíle, a převede ho na návratovou hodnotu valueboolint zdroje.

Pokud datová vazba obsahuje také nastavení, je před formátem výsledku jako řetězec vyvolán převaděč StringFormat hodnot.

Stránka Povolit tlačítka vukázce ukázek datových vazeb ukazuje, jak použít tento převaděč hodnot v datové vazbě. Vytvoří IntToBoolConverter se instance ve slovníku prostředků stránky. Pak se na něj odkazuje s StaticResource rozšířením značek pro nastavení vlastnosti ve dvou Converter datových vazbách. Je velmi běžné sdílet převaděče dat mezi více datovými vazbami na stránce:

<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.EnableButtonsPage"
             Title="Enable Buttons">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:IntToBoolConverter x:Key="intToBool" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <Entry x:Name="entry1"
               Text=""
               Placeholder="enter search term"
               VerticalOptions="CenterAndExpand" />

        <Button Text="Search"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                IsEnabled="{Binding Source={x:Reference entry1},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />

        <Entry x:Name="entry2"
               Text=""
               Placeholder="enter destination"
               VerticalOptions="CenterAndExpand" />

        <Button Text="Submit"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                IsEnabled="{Binding Source={x:Reference entry2},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
    </StackLayout>
</ContentPage>

Pokud se konvertor hodnot používá na více stránkách aplikace, můžete vytvořit instanci ve slovníku prostředků v souboru App.xaml.

Stránka Povolit tlačítka ukazuje běžnou potřebu při provádění operace na základě textu, který uživatel zadá do Entry zobrazení. Pokud se do objektu nic Entry nezadat, měl by být Button zakázaný. Každý Button objekt obsahuje datovou vazbu na svou IsEnabled vlastnost . Zdroj datové vazby je Length vlastnost Text vlastnosti odpovídajícího Entry objektu . Pokud tato Length vlastnost není 0, vrátí se převaděč hodnot a true je Button povolena hodnota :

Povolit tlačítkaPovolit

Všimněte Text si, že vlastnost v každé Entry z nich je inicializována na prázdný řetězec. Vlastnost Text je ve výchozím nastavení a datová vazba v takovém případě nebude null fungovat.

Některé převaděče hodnot jsou napsány speciálně pro konkrétní aplikace, zatímco jiné jsou generalizovány. Pokud víte, že převaděč hodnot se bude používat pouze ve OneWay vazbách, může ConvertBack metoda jednoduše vrátit null .

Výše uvedená metoda implicitně předpokládá, že argument je typu a Convertvalueint návratová hodnota musí být typu bool . Podobně metoda ConvertBack předpokládá, že argument je typu a valuebool návratová hodnota je int . Pokud tomu tak není, dojde k výjimce modulu runtime.

Můžete napsat převaděče hodnot, které budou zobecněnější a přijímat několik různých typů dat. Metody a mohou používat operátory nebo s parametrem nebo mohou volat u tohoto parametru, aby určily jeho typ, a pak ConvertConvertBack provést něco asisvalueGetType vhodného. Očekávaný typ návratové hodnoty každé metody je dán targetType parametrem . V některých případech se převaděče hodnot používají s datovými vazbami různých cílových typů. Převaděč hodnot může pomocí targetType argumentu provést převod správného typu.

Pokud je prováděný převod pro různé jazykové verze jiný, použijte culture pro tento účel parametr . Argument parameter pro a je popsán dále v tomto ConvertConvertBack článku.

Vlastnosti převaděče vazeb

Třídy převaděče hodnot mohou mít vlastnosti a obecné parametry. Tento převaděč konkrétní hodnoty převede objekt bool ze zdroje na objekt typu pro T cíl:

public class BoolToObjectConverter<T> : IValueConverter
{
    public T TrueObject { set; get; }

    public T FalseObject { set; get; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? TrueObject : FalseObject;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((T)value).Equals(TrueObject);
    }
}

Stránka Switch Indicators (Indikátory přepínače) ukazuje, jak se může použít k zobrazení hodnoty zobrazení. I když je běžné vytvořit instanci převaděčů hodnot jako prostředků ve slovníku prostředků, tato stránka ukazuje alternativu: Každá instance konvertoru hodnot je vytvořena mezi značkami Binding.Converter property-element. Označuje obecný argument a a jsou x:TypeArgumentsTrueObject obě FalseObject nastaveny na objekty tohoto typu:

<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.SwitchIndicatorsPage"
             Title="Switch Indicators">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Label">
                <Setter Property="FontSize" Value="18" />
                <Setter Property="VerticalOptions" Value="Center" />
            </Style>

            <Style TargetType="Switch">
                <Setter Property="VerticalOptions" Value="Center" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <StackLayout Orientation="Horizontal"
                     VerticalOptions="CenterAndExpand">
            <Label Text="Subscribe?" />
            <Switch x:Name="switch1" />
            <Label>
                <Label.Text>
                    <Binding Source="{x:Reference switch1}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="x:String"
                                                         TrueObject="Of course!"
                                                         FalseObject="No way!" />
                        </Binding.Converter>
                    </Binding>
                </Label.Text>
            </Label>
        </StackLayout>

        <StackLayout Orientation="Horizontal"
                     VerticalOptions="CenterAndExpand">
            <Label Text="Allow popups?" />
            <Switch x:Name="switch2" />
            <Label>
                <Label.Text>
                    <Binding Source="{x:Reference switch2}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="x:String"
                                                         TrueObject="Yes"
                                                         FalseObject="No" />
                        </Binding.Converter>
                    </Binding>
                </Label.Text>
                <Label.TextColor>
                    <Binding Source="{x:Reference switch2}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="Color"
                                                         TrueObject="Green"
                                                         FalseObject="Red" />
                        </Binding.Converter>
                    </Binding>
                </Label.TextColor>
            </Label>
        </StackLayout>

        <StackLayout Orientation="Horizontal"
                     VerticalOptions="CenterAndExpand">
            <Label Text="Learn more?" />
            <Switch x:Name="switch3" />
            <Label FontSize="18"
                   VerticalOptions="Center">
                <Label.Style>
                    <Binding Source="{x:Reference switch3}"
                             Path="IsToggled">
                        <Binding.Converter>
                            <local:BoolToObjectConverter x:TypeArguments="Style">
                                <local:BoolToObjectConverter.TrueObject>
                                    <Style TargetType="Label">
                                        <Setter Property="Text" Value="Indubitably!" />
                                        <Setter Property="FontAttributes" Value="Italic, Bold" />
                                        <Setter Property="TextColor" Value="Green" />
                                    </Style>                                    
                                </local:BoolToObjectConverter.TrueObject>

                                <local:BoolToObjectConverter.FalseObject>
                                    <Style TargetType="Label">
                                        <Setter Property="Text" Value="Maybe later" />
                                        <Setter Property="FontAttributes" Value="None" />
                                        <Setter Property="TextColor" Value="Red" />
                                    </Style>
                                </local:BoolToObjectConverter.FalseObject>
                            </local:BoolToObjectConverter>
                        </Binding.Converter>
                    </Binding>
                </Label.Style>
            </Label>
        </StackLayout>
    </StackLayout>
</ContentPage>

V posledních třech párech a je obecný argument nastavený na a celé objekty jsou k dispozici pro hodnoty a SwitchLabelStyleStyleTrueObjectFalseObject . Přepíší implicitní styl pro sadu ve slovníku prostředků, takže vlastnosti v tomto stylu jsou explicitně Label přiřazeny objektu Label . Přepínání Switch způsobí, že odpovídající Label změna bude odrážet:

přepínače Indikátory přepínače

Je také možné použít k implementaci podobných změn v Triggers uživatelském rozhraní na základě jiných zobrazení.

Parametry převaděče vazeb

Třída definuje vlastnost BindingBinding Xamarin_Forms _Binding_ConverterParameter" data-linktype="absolute-path">a rozšíření značek také definuje ConverterParameter vlastnost Xamarin_Forms Binding _Xaml_BindingExtension_ConverterParameter" data-linktype="absolute-path">. ConverterParameter Pokud je tato vlastnost nastavena, předá se hodnota metodám a ConvertConvertBack jako argument parameter . I v případě, že je instance konvertoru hodnot sdílena mezi několika datovými vazbami, může být objekt odlišný, aby mohl ConverterParameter provádět poněkud odlišné převody.

Použití je ConverterParameter předvedené pomocí programu pro výběr barev. V tomto případě má objekt tři vlastnosti typu s názvem , a , který používá RgbColorViewModeldouble k vytvoření RedGreenBlueColor hodnoty:

public class RgbColorViewModel : INotifyPropertyChanged
{
    Color color;
    string name;

    public event PropertyChangedEventHandler PropertyChanged;

    public double Red
    {
        set
        {
            if (color.R != value)
            {
                Color = new Color(value, color.G, color.B);
            }
        }
        get
        {
            return color.R;
        }
    }

    public double Green
    {
        set
        {
            if (color.G != value)
            {
                Color = new Color(color.R, value, color.B);
            }
        }
        get
        {
            return color.G;
        }
    }

    public double Blue
    {
        set
        {
            if (color.B != value)
            {
                Color = new Color(color.R, color.G, value);
            }
        }
        get
        {
            return color.B;
        }
    }

    public Color Color
    {
        set
        {
            if (color != value)
            {
                color = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Red"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Green"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Blue"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));

                Name = NamedColor.GetNearestColorName(color);
            }
        }
        get
        {
            return color;
        }
    }

    public string Name
    {
        private set
        {
            if (name != value)
            {
                name = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
            }
        }
        get
        {
            return name;
        }
    }
}

Vlastnosti Red , a jsou v rozsahu od GreenBlue 0 do 1. Můžete ale dát přednost zobrazení součástí jako dvouciferné šestnáctkové hodnoty.

Chcete-li je zobrazit jako šestnáctkové hodnoty v jazyce XAML, musí být vynásobeny hodnotou 255, převedeny na celé číslo a poté formátovány pomocí specifikace "X2" ve StringFormat vlastnosti . První dva úkoly (vynásobení číslem 255 a převod na celé číslo) mohou být zpracovány převaděčem hodnot. Aby byl konvertor hodnot co nejobecnější, lze faktor násobení zadat pomocí vlastnosti , což znamená, že jako argument zadá metody ConverterParameterConvert a ConvertBackparameter :

public class DoubleToIntConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)Math.Round((double)value * GetParameter(parameter));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value / GetParameter(parameter);
    }

    double GetParameter(object parameter)
    {
        if (parameter is double)
            return (double)parameter;

        else if (parameter is int)
            return (int)parameter;

        else if (parameter is string)
            return double.Parse((string)parameter);

        return 1;
    }
}

Převede Convert z na při doubleint vynásobení hodnotou; argument celého čísla vydělí argumentem parameter a vrátí ConvertBackvalueparameterdouble výsledek. (V níže zobrazeném programu se převaděč hodnot používá pouze v souvislosti s formátováním řetězců, takže ConvertBack se nepoužívá.)

Typ argumentu se bude pravděpodobně lišit v závislosti na tom, jestli je datová vazba definovaná v kódu parameter nebo XAML. Pokud je ConverterParameter vlastnost Binding nastavená v kódu, bude pravděpodobně nastavená na číselnou hodnotu:

binding.ConverterParameter = 255;

Vlastnost ConverterParameter je typu , takže kompilátor Object jazyka C# interpretuje literál 255 jako celé číslo a nastaví vlastnost na hodnotu.

V jazyce XAML se ConverterParameter ale pravděpodobně nastaví tímto kódem:

<Label Text="{Binding Red,
                      Converter={StaticResource doubleToInt},
                      ConverterParameter=255,
                      StringFormat='Red = {0:X2}'}" />

Číslo 255 vypadá jako číslo, ale vzhledem k tomu, že je typu , parser XAML s ConverterParameterObject 255 zachází jako s řetězcem.

Z tohoto důvodu výše uvedený převaděč hodnot obsahuje samostatnou metodu, která zpracovává případy typu GetParameterparameter , nebo doubleintstring .

Stránka selektoru barev RGB vytvoří instanci ve svém slovníku prostředků podle definice dvou implicitních stylů:

<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.RgbColorSelectorPage"
             Title="RGB Color Selector">
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="Slider">
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>

            <Style TargetType="Label">
                <Setter Property="HorizontalTextAlignment" Value="Center" />
            </Style>

            <local:DoubleToIntConverter x:Key="doubleToInt" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <StackLayout.BindingContext>
            <local:RgbColorViewModel Color="Gray" />
        </StackLayout.BindingContext>

        <BoxView Color="{Binding Color}"
                 VerticalOptions="FillAndExpand" />

        <StackLayout Margin="10, 0">
            <Label Text="{Binding Name}" />

            <Slider Value="{Binding Red}" />
            <Label Text="{Binding Red,
                                  Converter={StaticResource doubleToInt},
                                  ConverterParameter=255,
                                  StringFormat='Red = {0:X2}'}" />

            <Slider Value="{Binding Green}" />
            <Label Text="{Binding Green,
                                  Converter={StaticResource doubleToInt},
                                  ConverterParameter=255,
                                  StringFormat='Green = {0:X2}'}" />

            <Slider Value="{Binding Blue}" />
            <Label>
                <Label.Text>
                    <Binding Path="Blue"
                             StringFormat="Blue = {0:X2}"
                             Converter="{StaticResource doubleToInt}">
                        <Binding.ConverterParameter>
                            <x:Double>255</x:Double>
                        </Binding.ConverterParameter>
                    </Binding>
                </Label.Text>
            </Label>
        </StackLayout>
    </StackLayout>
</ContentPage>    

Hodnoty vlastností RedGreen a se zobrazí s Binding rozšířením značek. Vlastnost však vytvoří instanci třídy , aby BlueBinding bylo možné předvést, jak lze explicitní hodnotu double nastavit na vlastnost ConverterParameter .

Tady je výsledek:

RGB Selektor barev