Bagikan melalui


Membuat Ekstensi Markup XAML

Pada tingkat terprogram, ekstensi markup XAML adalah kelas yang mengimplementasikan IMarkupExtension antarmuka atau IMarkupExtension<T> . Anda dapat menjelajahi kode sumber ekstensi markup standar yang dijelaskan di bawah ini di direktori MarkupExtensions repositori Xamarin.Forms GitHub.

Anda juga dapat menentukan ekstensi markup XAML kustom Anda sendiri dengan berasal dari IMarkupExtension atau IMarkupExtension<T>. Gunakan formulir generik jika ekstensi markup mendapatkan nilai dari jenis tertentu. Ini adalah kasus dengan beberapa Xamarin.Forms ekstensi markup:

  • TypeExtension berasal dari IMarkupExtension<Type>
  • ArrayExtension berasal dari IMarkupExtension<Array>
  • DynamicResourceExtension berasal dari IMarkupExtension<DynamicResource>
  • BindingExtension berasal dari IMarkupExtension<BindingBase>
  • ConstraintExpression berasal dari IMarkupExtension<Constraint>

Kedua IMarkupExtension antarmuka hanya menentukan satu metode masing-masing, bernama ProvideValue:

public interface IMarkupExtension
{
    object ProvideValue(IServiceProvider serviceProvider);
}

public interface IMarkupExtension<out T> : IMarkupExtension
{
    new T ProvideValue(IServiceProvider serviceProvider);
}

Karena IMarkupExtension<T> berasal dari IMarkupExtension dan menyertakan new kata kunci pada ProvideValue, kata kunci berisi kedua ProvideValue metode.

Sangat sering, ekstensi markup XAML menentukan properti yang berkontribusi pada nilai pengembalian. (Pengecualian yang jelas adalah NullExtension, di mana ProvideValue hanya mengembalikan null.) Metode ProvideValue ini memiliki argumen tunggal jenis IServiceProvider yang akan dibahas nanti dalam artikel ini.

Ekstensi Markup untuk Menentukan Warna

Ekstensi markup XAML berikut memungkinkan Anda membuat Color nilai menggunakan komponen hue, saturasi, dan luminositas. Ini mendefinisikan empat properti untuk empat komponen warna, termasuk komponen alfa yang diinisialisasi menjadi 1. Kelas berasal dari IMarkupExtension<Color> untuk menunjukkan nilai pengembalian Color :

public class HslColorExtension : IMarkupExtension<Color>
{
    public double H { set; get; }

    public double S { set; get; }

    public double L { set; get; }

    public double A { set; get; } = 1.0;

    public Color ProvideValue(IServiceProvider serviceProvider)
    {
        return Color.FromHsla(H, S, L, A);
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<Color>).ProvideValue(serviceProvider);
    }
}

Karena IMarkupExtension<T> berasal dari IMarkupExtension, kelas harus berisi dua ProvideValue metode, satu yang mengembalikan Color dan yang lain yang mengembalikan object, tetapi metode kedua cukup memanggil metode pertama.

Halaman Demo Warna HSL menunjukkan berbagai cara yang HslColorExtension dapat muncul dalam file XAML untuk menentukan warna untuk BoxView:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.HslColorDemoPage"
             Title="HSL Color Demo">

    <ContentPage.Resources>
        <ResourceDictionary>
            <Style TargetType="BoxView">
                <Setter Property="WidthRequest" Value="80" />
                <Setter Property="HeightRequest" Value="80" />
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <BoxView>
            <BoxView.Color>
                <local:HslColorExtension H="0" S="1" L="0.5" A="1" />
            </BoxView.Color>
        </BoxView>

        <BoxView>
            <BoxView.Color>
                <local:HslColor H="0.33" S="1" L="0.5" />
            </BoxView.Color>
        </BoxView>

        <BoxView Color="{local:HslColorExtension H=0.67, S=1, L=0.5}" />

        <BoxView Color="{local:HslColor H=0, S=0, L=0.5}" />

        <BoxView Color="{local:HslColor A=0.5}" />
    </StackLayout>
</ContentPage>

Perhatikan bahwa ketika HslColorExtension adalah tag XML, empat properti diatur sebagai atribut, tetapi ketika muncul di antara kurung kurawal, keempat properti dipisahkan oleh koma tanpa tanda kutip. Nilai default untuk H, , dan L adalah 0, dan nilai A default adalah 1, sehingga properti tersebut dapat dihilangkan jika Anda ingin nilai default diatur Ske nilai default. Contoh terakhir menunjukkan contoh di mana luminositas adalah 0, yang biasanya menghasilkan hitam, tetapi saluran alfa adalah 0,5, sehingga setengah transparan dan tampak abu-abu terhadap latar belakang putih halaman:

Demo Warna HSL

Ekstensi Markup untuk Mengakses Bitmap

Argumen ke ProvideValue adalah objek yang mengimplementasikan IServiceProvider antarmuka, yang didefinisikan dalam namespace .NET System . Antarmuka ini memiliki satu anggota, metode bernama GetService dengan Type argumen.

Kelas ImageResourceExtension yang ditunjukkan di bawah ini menunjukkan satu kemungkinan penggunaan IServiceProvider dan GetService untuk mendapatkan IXmlLineInfoProvider objek yang dapat memberikan informasi baris dan karakter yang menunjukkan di mana kesalahan tertentu terdeteksi. Dalam hal ini, pengecualian dinaikkan ketika Source properti belum ditetapkan:

[ContentProperty("Source")]
class ImageResourceExtension : IMarkupExtension<ImageSource>
{
    public string Source { set; get; }

    public ImageSource ProvideValue(IServiceProvider serviceProvider)
    {
        if (String.IsNullOrEmpty(Source))
        {
            IXmlLineInfoProvider lineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
            IXmlLineInfo lineInfo = (lineInfoProvider != null) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
            throw new XamlParseException("ImageResourceExtension requires Source property to be set", lineInfo);
        }

        string assemblyName = GetType().GetTypeInfo().Assembly.GetName().Name;
        return ImageSource.FromResource(assemblyName + "." + Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
    }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return (this as IMarkupExtension<ImageSource>).ProvideValue(serviceProvider);
    }
}

ImageResourceExtension sangat membantu ketika file XAML perlu mengakses file gambar yang disimpan sebagai sumber daya yang disematkan dalam proyek pustaka .NET Standard. Ini menggunakan Source properti untuk memanggil metode statis ImageSource.FromResource . Metode ini memerlukan nama sumber daya yang sepenuhnya memenuhi syarat, yang terdiri dari nama rakitan, nama folder, dan nama file yang dipisahkan oleh titik. Argumen kedua untuk ImageSource.FromResource metode ini menyediakan nama rakitan, dan hanya diperlukan untuk rilis build pada UWP. Terlepas dari itu, ImageSource.FromResource harus dipanggil dari rakitan yang berisi bitmap, yang berarti bahwa ekstensi sumber daya XAML ini tidak dapat menjadi bagian dari pustaka eksternal kecuali gambar juga ada di pustaka tersebut. (Lihat Artikel Gambar Tersemat untuk informasi selengkapnya tentang mengakses bitmap yang disimpan sebagai sumber daya yang disematkan.)

Meskipun ImageResourceExtension mengharuskan Source properti diatur, Source properti ditunjukkan dalam atribut sebagai properti konten kelas. Ini berarti bahwa Source= bagian ekspresi dalam kurung kurawal dapat dihilangkan. Di halaman Demo Sumber Daya Gambar, Image elemen mengambil dua gambar menggunakan nama folder dan nama file yang dipisahkan oleh titik:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.ImageResourceDemoPage"
             Title="Image Resource Demo">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Image Source="{local:ImageResource Images.SeatedMonkey.jpg}"
               Grid.Row="0" />

        <Image Source="{local:ImageResource Images.FacePalm.jpg}"
               Grid.Row="1" />

    </Grid>
</ContentPage>

Berikut adalah program yang berjalan:

Demo Sumber Daya Gambar

Penyedia Layanan

Dengan menggunakan IServiceProvider argumen ke ProvideValueekstensi markup XAML bisa mendapatkan akses ke informasi bermanfaat tentang file XAML tempat mereka digunakan. Tetapi untuk menggunakan IServiceProvider argumen dengan sukses, Anda perlu mengetahui jenis layanan apa yang tersedia dalam konteks tertentu. Cara terbaik untuk mendapatkan pemahaman tentang fitur ini adalah dengan mempelajari kode sumber ekstensi markup XAML yang ada di folder MarkupExtensions di Xamarin.Forms repositori di GitHub. Ketahuilah bahwa beberapa jenis layanan bersifat internal untuk Xamarin.Forms.

Dalam beberapa ekstensi markup XAML, layanan ini mungkin berguna:

 IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

Antarmuka IProvideValueTarget mendefinisikan dua properti, TargetObject dan TargetProperty. Ketika informasi ini diperoleh di ImageResourceExtension kelas , TargetObject adalah Image dan TargetProperty merupakan BindableProperty objek untuk Source properti .Image Ini adalah properti tempat ekstensi markup XAML telah diatur.

Panggilan GetService dengan argumen typeof(IProvideValueTarget) benar-benar mengembalikan objek jenis SimpleValueTargetProvider, yang didefinisikan dalam Xamarin.Forms.Xaml.Internals namespace. Jika Anda melemparkan nilai GetService pengembalian ke jenis tersebutGrid, Anda juga dapat mengakses ParentObjects properti, yang merupakan array yang berisi Image elemen, Grid induk, dan ImageResourceDemoPage induk dari .

Kesimpulan

Ekstensi markup XAML memainkan peran penting dalam XAML dengan memperluas kemampuan untuk mengatur atribut dari berbagai sumber. Selain itu, jika ekstensi markup XAML yang ada tidak menyediakan apa yang Anda butuhkan, Anda juga dapat menulis sendiri.