Xamarin.Forms Bağlama Değeri Dönüştürücüleri

Veri bağlamaları genellikle bir kaynak özelliğinden hedef özelliğe ve bazı durumlarda hedef özelliğinden kaynak özelliğe veri aktarır. Bu aktarım, kaynak ve hedef özellikler aynı türde olduğunda veya bir türün örtük dönüştürme yoluyla diğer türe dönüştürülebildiği durumlarda basittir. Böyle bir durum söz konusu olmadığında, bir tür dönüştürme gerçekleştirilmelidir.

Dize Biçimlendirme makalesinde, herhangi bir türü dizeye dönüştürmek için veri bağlama özelliğini nasıl kullanabileceğinizi StringFormat gördünüz. Diğer dönüştürme türleri için arabirimini uygulayan bir sınıfta bazı özel kodlar IValueConverter yazmanız gerekir. (Evrensel Windows Platformu ad alanında Windows.UI.Xaml.Data adlı IValueConverter benzer bir sınıf içerir, ancak bu IValueConverter ad alanındadırXamarin.Forms.) Uygulayan IValueConverter sınıflar değer dönüştürücüleri olarak adlandırılır, ancak bunlar genellikle bağlama dönüştürücüleri veya bağlama değer dönüştürücüleri olarak da adlandırılır.

IValueConverter Arabirimi

Kaynak özelliğin türünde int olduğu ancak hedef özelliğin bir boololduğu bir veri bağlaması tanımlamak istediğinizi varsayalım. Bu veri bağlamasının, tamsayı kaynağı 0'a eşit olduğunda bir false değer üretmesini ve true aksi takdirde olmasını istiyorsunuz.

Bunu, arabirimini uygulayan IValueConverter bir sınıfla yapabilirsiniz:

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

Bu sınıfın bir örneğini sınıfın Converter Binding özelliğine veya Converter işaretleme uzantısının özelliğine Binding ayarlarsınız. Bu sınıf, veri bağlamanın bir parçası olur.

veri Convert kaynağından veya bağlamalarındaki hedefe geçtiğinde OneWay TwoWay yöntemi çağrılır. value parametresi, veri bağlama kaynağındaki nesne veya değerdir. yöntemi, veri bağlama hedefinin türünde bir değer döndürmelidir. Burada gösterilen yöntem parametresini bir int değerine value dönüştürür ve ardından dönüş değeri için bool 0 ile karşılaştırır.

ConvertBack yöntemi, veriler hedeften veya OneWayToSource bağlamalarındaki kaynağa geçtiğinde TwoWay çağrılır. ConvertBack ters dönüştürme gerçekleştirir: Parametresinin value hedeften bir bool olduğunu varsayar ve bunu kaynak için bir int dönüş değerine dönüştürür.

Veri bağlama bir StringFormat ayar da içeriyorsa, sonuç dize olarak biçimlendirilmeden önce değer dönüştürücüsü çağrılır.

Örnekteki Düğmeleri Etkinleştir sayfası, bu değer dönüştürücüsunun bir veri bağlamasında nasıl kullanılacağını gösterir. IntToBoolConverter, sayfanın kaynak sözlüğünde örneği oluşturulur. Ardından özelliği iki veri bağlamasında ayarlamak Converter için bir StaticResource işaretleme uzantısıyla başvurulur. Veri dönüştürücülerini sayfadaki birden çok veri bağlaması arasında paylaşmak çok yaygındır:

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

Uygulamanızın birden çok sayfasında bir değer dönüştürücüsü kullanılıyorsa, app.xaml dosyasındaki kaynak sözlüğünde örneği oluşturabilirsiniz.

Düğmeleri Etkinleştir sayfası, kullanıcının bir görünüme girdiği metne göre bir işlem gerçekleştirdiğinde Button yaygın bir Entry gereksinim gösterir. içine hiçbir şey yazılmadıysa Entry, Button devre dışı bırakılmalıdır. Her Button birinin özelliğinde bir veri bağlaması IsEnabled vardır. Veri bağlama kaynağı, ilgili Entryözelliğinin özelliğidir.Text Length Bu Length özellik 0 değilse, değer dönüştürücüsü döndürülüyor true ve Button etkin:

Düğmeleri Etkinleştir

Her Entry bir içindeki özelliğinin Text boş bir dizeye başlatıldığına dikkat edin. Text özelliği varsayılan olarakdır null ve bu durumda veri bağlama çalışmaz.

Bazı değer dönüştürücüleri özel olarak belirli uygulamalar için yazılırken, diğerleri genelleştirilir. Değer dönüştürücüsünü yalnızca bağlamalarda OneWay kullanılabileceğini biliyorsanız yöntemi ConvertBack yalnızca döndürebilir null.

Convert Yukarıda gösterilen yöntem, bağımsız değişkenin value türünde olduğunu ve dönüş değerinin türünde int boololması gerektiğini örtük olarak varsayar. Benzer şekilde, ConvertBack yöntemi bağımsız değişkenin value türünde bool ve dönüş değerinin olduğunu intvarsayar. Böyle bir durum söz konusu değilse, bir çalışma zamanı özel durumu oluşur.

Daha genelleştirilecek ve birkaç farklı veri türünü kabul etmek için değer dönüştürücüleri yazabilirsiniz. Convert ve ConvertBack yöntemleri parametresiyle value veya is işleçlerini kullanabilir as veya türünü belirlemek için bu parametreyi çağırabilir GetType ve ardından uygun bir şey yapabilir. Her yöntemin dönüş değerinin beklenen türü parametresi tarafından targetType verilir. Bazen değer dönüştürücüleri farklı hedef türlerdeki veri bağlamalarıyla kullanılır; değer dönüştürücüsü, doğru tür için bir dönüştürme gerçekleştirmek üzere bağımsız değişkenini kullanabilir targetType .

Gerçekleştirilen dönüştürme farklı kültürler için farklıysa, bu amaç için parametresini culture kullanın. parameter ve ConvertBack bağımsız değişkeni Convert bu makalenin devamında ele alınmalıdır.

Bağlayıcı Dönüştürücü Özellikleri

Değer dönüştürücü sınıflarının özellikleri ve genel parametreleri olabilir. Bu belirli değer dönüştürücüsü, kaynaktan hedef için türünde T bir nesneye dönüştürürbool:

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

Göstergeleri Değiştir sayfası, bir Switch görünümün değerini görüntülemek için nasıl kullanılabileceğini gösterir. Değer dönüştürücülerinin kaynak sözlüğünde kaynak olarak örneğini oluşturmak yaygın olsa da, bu sayfada bir alternatif gösterilmektedir: Her değer dönüştürücüsü, özellik öğesi etiketleri arasında Binding.Converter örneklenir. x:TypeArguments, genel bağımsız değişkeni gösterir ve TrueObject FalseObject her ikisi de bu tür nesnelere ayarlanır:

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

Üç Switch ve Label çiftinin son kısmında genel bağımsız değişken olarak Styleayarlanır ve ve FalseObjectdeğerleri TrueObject için tüm Style nesneler sağlanır. Bunlar, kaynak sözlüğünde ayarlanan örtük stili Label geçersiz kılar, böylece bu stildeki özellikler açıkça öğesine Labelatanır. geçişini yapmak Switch , karşılık gelenin Label değişikliği yansıtmasına neden olur:

Göstergeleri Değiştir

Kullanıcı arabiriminde diğer görünümlere göre benzer değişiklikler uygulamak için de kullanabilirsiniz Triggers .

Bağlayıcı Dönüştürücü Parametreleri

Binding sınıfı bir ConverterParameter özelliği Binding ve işaretleme uzantısı da bir ConverterParameter özelliği tanımlar. Bu özellik ayarlanırsa, değer bağımsız değişken olarak ve ConvertBack yöntemlerine parameter geçirilirConvert. Değer dönüştürücüsünün örneği birkaç veri bağlaması arasında paylaşılsa bile, ConverterParameter değeri biraz farklı dönüştürmeler gerçekleştirmek için farklı olabilir.

kullanımı ConverterParameter bir renk seçimi programıyla gösterilir. Bu durumda , RgbColorViewModel adlı GreenRedtüründe double üç özelliği vardır ve Blue bir Color değer oluşturmak için bunu kullanır:

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

Red, Greenve Blue özellikleri 0 ile 1 arasında değişir. Ancak, bileşenlerin iki basamaklı onaltılık değerler olarak görüntülenmesini tercih edebilirsiniz.

Bunları XAML'de onaltılık değerler olarak görüntülemek için, bunların 255 ile çarpılması, tamsayıya dönüştürülmesi ve ardından özelliğinde StringFormat "X2" belirtimi ile biçimlendirilmesi gerekir. İlk iki görev (255 ile çarpılarak ve tamsayıya dönüştürülerek) değer dönüştürücüsü tarafından işlenebilir. Değer dönüştürücüsünün mümkün olduğunca genelleştirilmesi için çarpma faktörü özelliğiyle ConverterParameter belirtilebilir; başka bir deyişle bağımsız değişken olarak parameter ve ConvertBack yöntemlerini girerConvert:

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

değeriyle Convert çarparken parameter a'dan int double değerine dönüştürür; ConvertBack tamsayı value bağımsız değişkenini ile parameter böler ve bir double sonuç döndürür. (Aşağıda gösterilen programda, değer dönüştürücüsü yalnızca dize biçimlendirmesiyle bağlantılı olarak kullanılır, bu nedenle ConvertBack kullanılmaz.)

Bağımsız değişkenin türü, veri bağlamanın parameter kodda mı yoksa XAML'de mi tanımlandığına bağlı olarak farklı olabilir. ConverterParameter özelliği Binding kodda ayarlandıysa, büyük olasılıkla sayısal bir değere ayarlanmıştır:

binding.ConverterParameter = 255;

ConverterParameter özelliği türünde Objectolduğundan, C# derleyicisi değişmez değeri 255'i tamsayı olarak yorumlar ve özelliği bu değere ayarlar.

Ancak ConverterParameter XAML'de şu şekilde ayarlanmış olabilir:

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

255 bir sayı gibi görünür, ancak türünden Objectdolayı ConverterParameter XAML ayrıştırıcısı 255'i dize olarak ele alır.

Bu nedenle, yukarıda gösterilen değer dönüştürücüsü , veya türünde olması için parameter servis taleplerini işleyen ayrı GetParameter bir yöntem içerir.doublestringint

RGB Renk Seçici sayfası, iki örtük stilin tanımından sonra kaynak sözlüğünde örnek DoubleToIntConverter olarak gösterilir:

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

ve Green özelliklerinin değerleri Red bir Binding işaretleme uzantısıyla görüntülenir. Blue Ancak özelliği, açık double bir değerin özelliğine nasıl ayarlanabileceğini Binding göstermek için sınıfını ConverterParameter başlatır.

Sonuç şu şekildedir:

RGB Renk Seçici