Bagikan melalui


Menyesuaikan kontrol dengan handler

Telusuri sampel. Telusuri sampel

Handler dapat disesuaikan untuk menambah tampilan dan perilaku kontrol lintas platform di luar penyesuaian yang dimungkinkan melalui API kontrol. Penyesuaian ini, yang memodifikasi tampilan asli untuk kontrol lintas platform, dicapai dengan memodifikasi pemeta untuk handler dengan salah satu metode berikut:

  • PrependToMapping, yang memodifikasi pemeta untuk handler sebelum pemetaan kontrol .NET MAUI telah diterapkan.
  • ModifyMapping, yang memodifikasi pemetaan yang ada.
  • AppendToMapping, yang memodifikasi pemeta untuk handler setelah pemetaan kontrol .NET MAUI diterapkan.

Masing-masing metode ini memiliki tanda tangan identik yang memerlukan dua argumen:

  • Kunci stringberbasis. Saat memodifikasi salah satu pemetaan yang disediakan oleh .NET MAUI, kunci yang digunakan oleh .NET MAUI harus ditentukan. Nilai kunci yang digunakan oleh pemetaan kontrol .NET MAUI didasarkan pada antarmuka dan nama properti, misalnya nameof(IEntry.IsPassword). Antarmuka, dan propertinya, yang mengabstraksi setiap kontrol lintas platform dapat ditemukan di sini. Ini adalah format kunci yang harus digunakan jika Anda ingin penyesuaian handler Anda berjalan setiap kali properti berubah. Jika tidak, kunci dapat menjadi nilai arbitrer yang tidak harus sesuai dengan nama properti yang diekspos oleh jenis. Misalnya, MyCustomization dapat ditentukan sebagai kunci, dengan modifikasi tampilan asli apa pun dilakukan sebagai kustomisasi. Namun, konsekuensi dari format kunci ini adalah bahwa penyesuaian handler Anda hanya akan dijalankan ketika pemeta untuk handler pertama kali dimodifikasi.
  • Yang Action mewakili metode yang melakukan penyesuaian handler. Action menentukan dua argumen:
    • Argumen handler yang menyediakan instans handler yang sedang dikustomisasi.
    • Argumen view yang menyediakan instans kontrol lintas platform yang diterapkan handler.

Penting

Penyesuaian handler bersifat global dan tidak tercakup ke instans kontrol tertentu. Penyesuaian handler diizinkan untuk terjadi di mana saja di aplikasi Anda. Setelah handler disesuaikan, ini memengaruhi semua kontrol jenis tersebut, di mana saja di aplikasi Anda.

Setiap kelas handler mengekspos tampilan asli untuk kontrol lintas platform melalui propertinya PlatformView . Properti ini dapat diakses untuk mengatur properti tampilan asli, memanggil metode tampilan asli, dan berlangganan peristiwa tampilan asli. Selain itu, kontrol lintas platform yang diterapkan oleh handler diekspos melalui propertinya VirtualView .

Penghandel dapat disesuaikan per platform dengan menggunakan kompilasi kondisional, ke kode multi-target berdasarkan platform. Atau, Anda dapat menggunakan kelas parsial untuk mengatur kode Anda ke dalam folder dan file khusus platform. Untuk informasi selengkapnya tentang kompilasi bersyarah, lihat Kompilasi bersyar.

Mengkustomisasi kontrol

Tampilan MAUI Entry .NET adalah kontrol input teks satu baris, yang mengimplementasikan IEntry antarmuka. Memetakan EntryHandler Entry tampilan ke tampilan asli berikut untuk setiap platform:

  • Katalis iOS/Mac: UITextField
  • Android: AppCompatEditText
  • Windows: TextBox

Diagram berikut menunjukkan bagaimana tampilan dipetakan Entry ke tampilan aslinya melalui EntryHandler:

Arsitektur handler entri.

Pemeta Entry properti, di EntryHandler kelas , memetakan properti kontrol lintas platform ke API tampilan asli. Ini memastikan bahwa ketika properti diatur pada Entry, tampilan asli yang mendasar diperbarui sesuai kebutuhan.

Pemeta properti dapat dimodifikasi untuk disesuaikan Entry pada setiap platform:

namespace CustomizeHandlersDemo.Views;

public partial class CustomizeEntryPage : ContentPage
{
    public CustomizeEntryPage()
    {
        InitializeComponent();
        ModifyEntry();
    }

    void ModifyEntry()
    {
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
        {
#if ANDROID
            handler.PlatformView.SetSelectAllOnFocus(true);
#elif IOS || MACCATALYST
            handler.PlatformView.EditingDidBegin += (s, e) =>
            {
                handler.PlatformView.PerformSelector(new ObjCRuntime.Selector("selectAll"), null, 0.0f);
            };
#elif WINDOWS
            handler.PlatformView.GotFocus += (s, e) =>
            {
                handler.PlatformView.SelectAll();
            };
#endif
        });
    }
}

Dalam contoh ini, Entry kustomisasi terjadi di kelas halaman. Oleh karena itu, semua Entry kontrol di Android, iOS, dan Windows akan disesuaikan setelah instans CustomizeEntryPage dibuat. Kustomisasi dilakukan dengan mengakses properti handler PlatformView , yang menyediakan akses ke tampilan asli yang memetakan ke kontrol lintas platform pada setiap platform. Kode asli kemudian menyesuaikan handler dengan memilih semua teks di Entry saat mendapatkan fokus.

Untuk informasi selengkapnya tentang pemeta, lihat Pemeta.

Menyesuaikan instans kontrol tertentu

Handler bersifat global, dan menyesuaikan handler untuk kontrol akan menghasilkan semua kontrol dengan jenis yang sama yang disesuaikan di aplikasi Anda. Namun, handler untuk instans kontrol tertentu dapat disesuaikan dengan subkelas kontrol, lalu dengan memodifikasi handler untuk jenis kontrol dasar hanya ketika kontrol adalah jenis subkelas. Misalnya, untuk mengkustomisasi kontrol tertentu Entry pada halaman yang berisi beberapa Entry kontrol, Anda harus terlebih dahulu mensubkelas Entry kontrol:

namespace CustomizeHandlersDemo.Controls
{
    internal class MyEntry : Entry
    {
    }
}

Anda kemudian dapat menyesuaikan EntryHandler, melalui pemeta propertinya, untuk melakukan modifikasi yang diinginkan hanya untuk MyEntry instans:

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
    if (view is MyEntry)
    {
#if ANDROID
        handler.PlatformView.SetSelectAllOnFocus(true);
#elif IOS || MACCATALYST
        handler.PlatformView.EditingDidBegin += (s, e) =>
        {
            handler.PlatformView.PerformSelector(new ObjCRuntime.Selector("selectAll"), null, 0.0f);
        };
#elif WINDOWS
        handler.PlatformView.GotFocus += (s, e) =>
        {
            handler.PlatformView.SelectAll();
        };
#endif
    }
});

Jika penyesuaian handler dilakukan di kelas Anda App , instans apa pun MyEntry di aplikasi akan disesuaikan sesuai modifikasi handler.

Menyesuaikan kontrol menggunakan siklus hidup handler

Semua .NET MAUI berbasis handler mengontrol dukungan HandlerChanging dan HandlerChanged peristiwa. Peristiwa HandlerChanged ini dimunculkan ketika tampilan asli yang mengimplementasikan kontrol lintas platform tersedia dan diinisialisasi. Peristiwa HandlerChanging dinaikkan ketika handler kontrol akan dihapus dari kontrol lintas platform. Untuk informasi selengkapnya tentang peristiwa siklus hidup handler, lihat Siklus hidup handler.

Siklus hidup handler dapat digunakan untuk melakukan penyesuaian handler. Misalnya, untuk berlangganan, dan berhenti berlangganan dari, peristiwa tampilan asli, Anda harus mendaftarkan penanganan aktivitas untuk HandlerChanged peristiwa dan HandlerChanging pada kontrol lintas platform yang disesuaikan:

<Entry HandlerChanged="OnEntryHandlerChanged"
       HandlerChanging="OnEntryHandlerChanging" />

Penghandel dapat disesuaikan per platform dengan menggunakan kompilasi kondisional, atau dengan menggunakan kelas parsial untuk mengatur kode Anda ke dalam folder dan file khusus platform. Setiap pendekatan akan dibahas secara bergantian, dengan menyesuaikan Entry sehingga semua teksnya dipilih saat mendapatkan fokus.

Kompilasi kondisional

File code-behind yang berisi penanganan aktivitas untuk HandlerChanged peristiwa dan HandlerChanging ditampilkan dalam contoh berikut, yang menggunakan kompilasi bersyarah:

#if ANDROID
using AndroidX.AppCompat.Widget;
#elif IOS || MACCATALYST
using UIKit;
#elif WINDOWS
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
#endif

namespace CustomizeHandlersDemo.Views;

public partial class CustomizeEntryHandlerLifecyclePage : ContentPage
{
    public CustomizeEntryHandlerLifecyclePage()
    {
        InitializeComponent();
    }

    void OnEntryHandlerChanged(object sender, EventArgs e)
    {
        Entry entry = sender as Entry;
#if ANDROID
        (entry.Handler.PlatformView as AppCompatEditText).SetSelectAllOnFocus(true);
#elif IOS || MACCATALYST
        (entry.Handler.PlatformView as UITextField).EditingDidBegin += OnEditingDidBegin;
#elif WINDOWS
        (entry.Handler.PlatformView as TextBox).GotFocus += OnGotFocus;
#endif
    }

    void OnEntryHandlerChanging(object sender, HandlerChangingEventArgs e)
    {
        if (e.OldHandler != null)
        {
#if IOS || MACCATALYST
            (e.OldHandler.PlatformView as UITextField).EditingDidBegin -= OnEditingDidBegin;
#elif WINDOWS
            (e.OldHandler.PlatformView as TextBox).GotFocus -= OnGotFocus;
#endif
        }
    }

#if IOS || MACCATALYST                   
    void OnEditingDidBegin(object sender, EventArgs e)
    {
        var nativeView = sender as UITextField;
        nativeView.PerformSelector(new ObjCRuntime.Selector("selectAll"), null, 0.0f);
    }
#elif WINDOWS
    void OnGotFocus(object sender, RoutedEventArgs e)
    {
        var nativeView = sender as TextBox;
        nativeView.SelectAll();
    }
#endif
}

Peristiwa HandlerChanged ini dimunculkan setelah tampilan asli yang mengimplementasikan kontrol lintas platform telah dibuat dan diinisialisasi. Oleh karena itu, penanganan aktivitasnya adalah tempat langganan peristiwa asli harus dilakukan. Ini memerlukan transmisi PlatformView properti handler ke jenis, atau jenis dasar, dari tampilan asli sehingga peristiwa asli dapat diakses. Dalam contoh ini, di iOS, Mac Catalyst, dan Windows, OnEntryHandlerChanged peristiwa berlangganan peristiwa tampilan asli yang dinaikkan saat tampilan asli yang mengimplementasikan Entry fokus perolehan.

Penanganan OnEditingDidBegin aktivitas dan OnGotFocus mengakses tampilan asli untuk Entry di platform masing-masing, dan memilih semua teks yang ada di Entry.

Peristiwa HandlerChanging dinaikkan sebelum handler yang ada dihapus dari kontrol lintas platform, dan sebelum handler baru untuk kontrol lintas platform dibuat. Oleh karena itu, penanganan aktivitasnya adalah tempat langganan peristiwa asli harus dihapus, dan pembersihan lainnya harus dilakukan. Objek HandlerChangingEventArgs yang menyertai acara ini memiliki OldHandler properti dan NewHandler , yang akan diatur ke handler lama dan baru masing-masing. Dalam contoh ini, OnEntryHandlerChanging peristiwa menghapus langganan ke peristiwa tampilan asli di iOS, Mac Catalyst, dan Windows.

Kelas parsial

Daripada menggunakan kompilasi bersyarat, Anda juga dapat menggunakan kelas parsial untuk mengatur kode kustomisasi kontrol Anda ke dalam folder dan file khusus platform. Dengan pendekatan ini, kode kustomisasi Anda dipisahkan menjadi kelas parsial lintas platform dan kelas parsial khusus platform:

  • Kelas parsial lintas platform biasanya mendefinisikan anggota, tetapi tidak mengimplementasikannya, dan dibangun untuk semua platform. Kelas ini tidak boleh ditempatkan di folder anak Platform mana pun dari proyek Anda, karena melakukannya akan menjadikannya kelas khusus platform.
  • Kelas parsial khusus platform biasanya mengimplementasikan anggota yang ditentukan dalam kelas parsial lintas platform, dan dibangun untuk satu platform. Kelas ini harus ditempatkan di folder anak folder Platform untuk platform yang Anda pilih.

Contoh berikut menunjukkan kelas parsial lintas platform:

namespace CustomizeHandlersDemo.Views;

public partial class CustomizeEntryPartialMethodsPage : ContentPage
{
    public CustomizeEntryPartialMethodsPage()
    {
        InitializeComponent();
    }

    partial void ChangedHandler(object sender, EventArgs e);
    partial void ChangingHandler(object sender, HandlerChangingEventArgs e);

    void OnEntryHandlerChanged(object sender, EventArgs e) => ChangedHandler(sender, e);
    void OnEntryHandlerChanging(object sender, HandlerChangingEventArgs e) => ChangingHandler(sender, e);
}

Dalam contoh ini, dua penanganan aktivitas memanggil metode parsial bernama ChangedHandler dan ChangingHandler, yang tanda tangannya ditentukan dalam kelas parsial lintas platform. Implementasi metode parsial kemudian didefinisikan dalam kelas parsial khusus platform, yang harus ditempatkan di folder anak Platform yang benar untuk memastikan bahwa sistem build hanya mencoba membangun kode asli saat membangun platform tertentu. Misalnya, kode berikut menunjukkan CustomizeEntryPartialMethodsPage kelas di folder Platforms>Windows proyek:

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace CustomizeHandlersDemo.Views
{
    public partial class CustomizeEntryPartialMethodsPage : ContentPage
    {
        partial void ChangedHandler(object sender, EventArgs e)
        {
            Entry entry = sender as Entry;
            (entry.Handler.PlatformView as TextBox).GotFocus += OnGotFocus;
        }

        partial void ChangingHandler(object sender, HandlerChangingEventArgs e)
        {
            if (e.OldHandler != null)
            {
                (e.OldHandler.PlatformView as TextBox).GotFocus -= OnGotFocus;
            }
        }

        void OnGotFocus(object sender, RoutedEventArgs e)
        {
            var nativeView = sender as TextBox;
            nativeView.SelectAll();
        }
    }
}

Keuntungan dari pendekatan ini adalah bahwa kompilasi bersyarat tidak diperlukan, dan bahwa metode parsial tidak perlu diterapkan pada setiap platform. Jika implementasi tidak disediakan pada platform, maka metode dan semua panggilan ke metode akan dihapus pada waktu kompilasi. Untuk informasi tentang metode parsial, lihat Metode parsial.

Untuk informasi tentang organisasi folder Platform dalam proyek .NET MAUI, lihat Kelas dan metode parsial. Untuk informasi tentang cara mengonfigurasi multi-penargetan sehingga Anda tidak perlu menempatkan kode platform ke dalam sub-folder folder Platform , lihat Mengonfigurasi multi-penargetan.