Bagikan melalui


Pengikatan pengonversi nilai

Browse sample. Telusuri sampel

Pengikatan data .NET Multi-platform App UI (.NET MAUI) biasanya mentransfer data dari properti sumber ke properti target, dan dalam beberapa kasus dari properti target ke properti sumber. Transfer ini mudah ketika properti sumber dan target memiliki jenis yang sama, atau ketika satu jenis dapat dikonversi ke jenis lain melalui konversi implisit. Ketika itu tidak terjadi, konversi jenis harus terjadi.

Dalam artikel Pemformatan string, Anda melihat bagaimana Anda dapat menggunakan StringFormat properti pengikatan data untuk mengonversi jenis apa pun menjadi string. Untuk jenis konversi lainnya, Anda perlu menulis beberapa kode khusus di kelas yang mengimplementasikan IValueConverter antarmuka. Kelas yang mengimplementasikan IValueConverter disebut pengonversi nilai, tetapi juga sering disebut sebagai pengikatan pengonversi atau pengikatan pengonversi nilai.

Pengikatan pengonversi nilai

Misalkan Anda ingin menentukan pengikatan data di mana properti sumber berjenis int tetapi properti target adalah bool. Anda ingin pengikatan data ini menghasilkan false nilai ketika sumber bilangan bulat sama dengan 0, dan true sebaliknya. Ini dapat dicapai dengan kelas yang mengimplementasikan IValueConverter antarmuka:

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

Anda kemudian mengatur instans kelas ini ke Converter properti Binding kelas atau ke Converter properti Binding ekstensi markup. Kelas ini menjadi bagian dari pengikatan data.

Metode Convert ini dipanggil ketika data berpindah dari sumber ke target dalam OneWay atau TwoWay pengikatan. Parameter value adalah objek atau nilai dari sumber pengikatan data. Metode harus mengembalikan nilai dari jenis target pengikatan data. Metode yang ditunjukkan di sini melemparkan value parameter ke dan int kemudian membandingkannya dengan 0 untuk nilai yang bool dikembalikan.

Metode ConvertBack ini dipanggil ketika data berpindah dari target ke sumber dalam TwoWay atau OneWayToSource pengikatan. ConvertBack melakukan konversi yang berlawanan: Mengasumsikan value parameter adalah bool dari target, dan mengonversinya menjadi nilai pengembalian int untuk sumber.

Catatan

Jika pengikatan data juga menyertakan StringFormat pengaturan, pengonversi nilai dipanggil sebelum hasil diformat sebagai string.

Contoh berikut menunjukkan cara menggunakan pengonversi nilai ini dalam pengikatan data:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.EnableButtonsPage"
             Title="Enable Buttons">
    <ContentPage.Resources>
        <local:IntToBoolConverter x:Key="intToBool" />
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <Entry x:Name="entry1"
               Text=""
               Placeholder="enter search term"
               VerticalOptions="Center" />
        <Button x:DataType="Entry"
                Text="Search"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                IsEnabled="{Binding Source={x:Reference entry1},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
        <Entry x:Name="entry2"
               Text=""
               Placeholder="enter destination"
               VerticalOptions="Center" />
        <Button x:DataType="Entry"
                Text="Submit"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                IsEnabled="{Binding Source={x:Reference entry2},
                                    Path=Text.Length,
                                    Converter={StaticResource intToBool}}" />
    </StackLayout>
</ContentPage>

Dalam contoh ini, IntToBoolConverter dibuat dalam kamus sumber daya halaman. Kemudian dirujuk dengan StaticResource ekstensi markup untuk mengatur Converter properti dalam dua pengikatan data. Sangat umum untuk berbagi pengonversi data di antara beberapa pengikatan data di halaman. Jika pengonversi nilai digunakan di beberapa halaman aplikasi Anda, Anda dapat membuat instansnya dalam kamus sumber daya tingkat aplikasi.

Contoh ini menunjukkan kebutuhan umum saat Button melakukan operasi berdasarkan teks yang diketik pengguna ke dalam Entry tampilan. Properti Text masing-masing Entry diinisialisasi ke string kosong, karena Text properti secara null default, dan pengikatan data tidak akan berfungsi dalam kasus tersebut. Jika tidak ada yang ditik ke Entrydalam , Button harus dinonaktifkan. Masing-masing Button berisi pengikatan data pada propertinya IsEnabled . Sumber pengikatan data adalah Length properti properti Text dari yang sesuai Entry. Length Jika properti tersebut bukan 0, pengonversi nilai akan kembali true dan Button diaktifkan:

Enable buttons.

Catatan

Jika Anda tahu bahwa pengonversi nilai hanya akan digunakan dalam OneWay pengikatan, maka ConvertBack metode hanya dapat mengembalikan null.

Metode Convert yang ditunjukkan di atas mengasumsikan bahwa value argumen berjenis int dan nilai yang dikembalikan harus berjenis bool. Demikian pula, ConvertBack metode mengasumsikan bahwa value argumen berjenis bool dan nilai yang dikembalikan adalah int. Jika tidak demikian, pengecualian runtime akan terjadi.

Anda dapat menulis pengonversi nilai agar lebih umum dan menerima beberapa jenis data yang berbeda. Metode Convert dan ConvertBack dapat menggunakan as operator atau is dengan parameter , atau dapat memanggil GetType parameter tersebut value untuk menentukan jenisnya, dan kemudian melakukan sesuatu yang sesuai. Jenis nilai pengembalian setiap metode yang diharapkan diberikan oleh targetType parameter . Terkadang, pengonversi nilai digunakan dengan pengikatan data dari berbagai jenis target. Dalam hal ini, pengonversi nilai dapat menggunakan targetType argumen untuk melakukan konversi untuk jenis yang benar.

Jika konversi yang dilakukan berbeda untuk budaya yang berbeda, gunakan culture parameter untuk tujuan ini.

Mengikat properti pengonversi

Kelas pengonversi nilai dapat memiliki properti dan parameter generik. Pengonversi nilai berikut mengonversi bool dari sumber ke objek jenis T untuk target:

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

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

Contoh berikut menunjukkan bagaimana konverter ini dapat digunakan untuk menampilkan nilai Switch tampilan. Meskipun umum untuk membuat instans pengonversi nilai sebagai sumber daya dalam kamus sumber daya, contoh ini menunjukkan alternatif. Di sini, setiap pengonversi nilai dibuat di antara Binding.Converter tag elemen properti. x:TypeArguments menunjukkan argumen generik, dan dan TrueObject FalseObject keduanya diatur ke objek jenis tersebut:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.SwitchIndicatorsPage"
             Title="Switch Indicators">
    <ContentPage.Resources>
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="18" />
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>

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

    <StackLayout Padding="10, 0">
        <StackLayout Orientation="Horizontal"
                     VerticalOptions="Center">
            <Label Text="Subscribe?" />
            <Switch x:Name="switch1" />
            <Label>
                <Label.Text>
                    <Binding x:DataType="Switch"
                             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="Center">
            <Label Text="Allow popups?" />
            <Switch x:Name="switch2" />
            <Label>
                <Label.Text>
                    <Binding x:DataType="Switch"
                             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 x:DataType="Switch"
                             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="Center">
            <Label Text="Learn more?" />
            <Switch x:Name="switch3" />
            <Label FontSize="18"
                   VerticalOptions="Center">
                <Label.Style>
                    <Binding x:DataType="Switch"
                             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>

Dalam contoh ini, di terakhir dari tiga Switch pasangan dan Label , argumen generik diatur ke Style, dan seluruh Style objek disediakan untuk nilai TrueObject dan FalseObject. Ini mengambil alih gaya implisit untuk Label diatur dalam kamus sumber daya, sehingga properti dalam gaya tersebut Labelsecara eksplisit ditetapkan ke . Mengalihkan Switch penyebab yang sesuai Label untuk mencerminkan perubahan:

Switch indicators.

Catatan

Dimungkinkan juga untuk menggunakan pemicu untuk menerapkan perubahan di antarmuka pengguna berdasarkan tampilan lain. Untuk informasi selengkapnya, lihat Pemicu.

Mengikat parameter konverter

Kelas Binding menentukan ConverterParameter properti, dan Binding ekstensi markup juga menentukan ConverterParameter properti. Jika properti ini diatur, maka nilai diteruskan ke Convert metode dan ConvertBack sebagai parameter argumen. Bahkan jika instans pengonversi nilai dibagikan di antara beberapa pengikatan data, ConverterParameter bisa berbeda untuk melakukan konversi yang berbeda.

Penggunaan ConverterParameter properti dapat ditunjukkan dengan program pemilihan warna. Contoh berikut menunjukkan RgbColorViewModel, yang memiliki tiga properti jenis float bernama Red, Green, dan Blue yang digunakannya untuk membangun Color nilai:

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

    public event PropertyChangedEventHandler PropertyChanged;

    public float Red
    {
        get { return color.Red; }
        set
        {
            if (color.Red != value)
            {
                Color = new Color(value, color.Green, color.Blue);
            }
        }
    }

    public float Green
    {
        get { return color.Green; }
        set
        {
            if (color.Green != value)
            {
                Color = new Color(color.Red, value, color.Blue);
            }
        }
    }

    public float Blue
    {
        get { return color.Blue; }
        set
        {
            if (color.Blue != value)
            {
                Color = new Color(color.Red, color.Green, value);
            }
        }
    }

    public Color Color
    {
        get { return 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);
            }
        }
    }

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

Nilai Redproperti , Green, dan Blue dapat berkisar antara 0 dan 1. Namun, Anda mungkin lebih suka komponen ditampilkan sebagai nilai heksadesimal dua digit. Untuk menampilkan ini sebagai nilai heksadesimal di XAML, nilai tersebut harus dikalikan dengan 255, dikonversi menjadi bilangan bulat, lalu diformat dengan spesifikasi "X2" dalam StringFormat properti . Mengalikan dengan 255 dan mengonversi ke bilangan bulat dapat dilakukan oleh pengonversi nilai. Untuk membuat pengonversi nilai segeneral mungkin, faktor perkalian dapat ditentukan dengan ConverterParameter properti , yang berarti bahwa ia memasukkan Convert metode dan ConvertBack sebagai parameter argumen:

public class FloatToIntConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)Math.Round((float)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 float)
            return (float)parameter;
        else if (parameter is int)
            return (int)parameter;
        else if (parameter is string)
            return float.Parse((string)parameter);

        return 1;
    }
}

Dalam contoh ini, Convert metode mengonversi dari menjadi int float sementara dikalikan parameter dengan nilai . Metode ConvertBack membagi argumen bilangan bulat value dengan parameter dan mengembalikan hasil float .

Jenis parameter argumen kemungkinan berbeda tergantung pada apakah pengikatan data ditentukan dalam XAML atau kode. ConverterParameter Jika properti diatur Binding dalam kode, kemungkinan akan diatur ke nilai numerik:

binding.ConverterParameter = 255;

Properti ConverterParameter berjenis Object, sehingga pengkompilasi C# menginterpretasikan literal 255 sebagai bilangan bulat, dan mengatur properti ke nilai tersebut.

Namun, di XAML ConverterParameter kemungkinan akan diatur seperti ini:

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

Sementara 255 terlihat seperti angka, karena ConverterParameter berjenis Object, pengurai XAML memperlakukan 255 sebagai string. Untuk alasan ini, pengonversi nilai menyertakan metode terpisah GetParameter yang menangani kasus karena parameter jenis float, , intatau string.

Contoh XAML berikut membuat instans FloatToIntConverter dalam kamus sumber dayanya:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataBindingDemos"
             x:Class="DataBindingDemos.RgbColorSelectorPage"
             Title="RGB Color Selector"
             x:DataType="local:RgbColorViewModel">
    <ContentPage.BindingContext>
        <local:RgbColorViewModel Color="Gray" />
    </ContentPage.BindingContext>
    <ContentPage.Resources>
        <Style TargetType="Slider">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>

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

        <local:FloatToIntConverter x:Key="floatToInt" />
    </ContentPage.Resources>

    <StackLayout Margin="20">
        <BoxView Color="{Binding Color}"
                 HeightRequest="100"
                 WidthRequest="100"
                 HorizontalOptions="Center" />
        <StackLayout Margin="10, 0">
            <Label Text="{Binding Name}" />
            <Slider Value="{Binding Red}" />
            <Label Text="{Binding Red,
                                  Converter={StaticResource floatToInt},
                                  ConverterParameter=255,
                                  StringFormat='Red = {0:X2}'}" />
            <Slider Value="{Binding Green}" />
            <Label Text="{Binding Green,
                                  Converter={StaticResource floatToInt},
                                  ConverterParameter=255,
                                  StringFormat='Green = {0:X2}'}" />
            <Slider Value="{Binding Blue}" />
            <Label>
                <Label.Text>
                    <Binding Path="Blue"
                             StringFormat="Blue = {0:X2}"
                             Converter="{StaticResource floatToInt}">
                        <Binding.ConverterParameter>
                            <x:Single>255</x:Single>
                        </Binding.ConverterParameter>
                    </Binding>
                </Label.Text>
            </Label>
        </StackLayout>
    </StackLayout>
</ContentPage>

Nilai Red properti dan Green ditampilkan dengan Binding ekstensi markup. Properti Blue , bagaimanapun, membuat instans Binding kelas untuk menunjukkan bagaimana nilai eksplisit float dapat diatur ke ConverterParameter properti:

RGB color selector.