Udostępnij za pośrednictwem


Dostosowywanie kontrolek za pomocą programów obsługi

Przeglądaj przykład. Przeglądanie przykładu

Programy obsługi można dostosować w celu rozszerzenia wyglądu i zachowania kontrolki międzyplatformowej poza dostosowywanie, które jest możliwe za pośrednictwem interfejsu API kontrolki. To dostosowanie, które modyfikuje widoki natywne dla kontrolki międzyplatformowej, jest osiągane przez zmodyfikowanie mapera dla programu obsługi przy użyciu jednej z następujących metod:

  • PrependToMapping, który modyfikuje maper programu obsługi przed zastosowaniem mapowań kontrolek .NET MAUI.
  • ModifyMapping, który modyfikuje istniejące mapowanie.
  • AppendToMapping, który modyfikuje maper programu obsługi po zastosowaniu mapowań kontrolek .NET MAUI.

Każda z tych metod ma identyczny podpis, który wymaga dwóch argumentów:

  • stringKlucz oparty na protokole . Podczas modyfikowania jednego z mapowań dostarczonych przez program .NET MAUI należy określić klucz używany przez program .NET MAUI. Wartości kluczy używane przez mapowania kontrolek MAUI platformy .NET są oparte na nazwach interfejsów i właściwości, na przykład nameof(IEntry.IsPassword). Interfejsy i ich właściwości, które abstrakują poszczególne kontrolki międzyplatformowe, można znaleźć tutaj. Jest to format klucza, który powinien być używany, jeśli chcesz, aby dostosowanie programu obsługi było uruchamiane za każdym razem, gdy zmienia się właściwość. W przeciwnym razie klucz może być dowolną wartością, która nie musi odpowiadać nazwie właściwości uwidocznionej przez typ. Można na przykład MyCustomization określić jako klucz, z dowolną modyfikacją widoku natywnego wykonywaną jako dostosowanie. Jednak konsekwencją tego formatu klucza jest to, że dostosowanie programu obsługi zostanie uruchomione tylko wtedy, gdy maper programu obsługi zostanie po raz pierwszy zmodyfikowany.
  • Element Action reprezentujący metodę, która wykonuje dostosowywanie programu obsługi. Parametr Action określa dwa argumenty:
    • handler Argument, który udostępnia wystąpienie programu obsługi, który jest dostosowywany.
    • view Argument, który udostępnia wystąpienie kontrolki międzyplatformowej, którą implementuje program obsługi.

Ważne

Dostosowania procedury obsługi są globalne i nie są ograniczone do określonego wystąpienia kontrolki. Dostosowywanie programu obsługi może nastąpić w dowolnym miejscu w aplikacji. Po dostosowaniu procedury obsługi ma ona wpływ na wszystkie kontrolki tego typu, wszędzie w aplikacji.

Każda klasa obsługi uwidacznia widok macierzysty dla kontrolki międzyplatformowej za pośrednictwem jej PlatformView właściwości. Dostęp do tej właściwości można uzyskać, aby ustawić właściwości widoku natywnego, wywołać metody widoku natywnego i zasubskrybować zdarzenia widoku natywnego. Ponadto kontrolka międzyplatformowa zaimplementowana przez program obsługi jest uwidaczniona za pośrednictwem jego VirtualView właściwości.

Programy obsługi można dostosować na platformę przy użyciu kompilacji warunkowej w kodzie wielokierunkowym opartym na platformie. Alternatywnie można użyć klas częściowych do organizowania kodu w foldery i pliki specyficzne dla platformy. Aby uzyskać więcej informacji na temat kompilacji warunkowej, zobacz Kompilacja warunkowa.

Dostosowywanie kontrolki

Widok MAUI Entry platformy .NET to jednowierszowa kontrolka wprowadzania tekstu, która implementuje IEntry interfejs. Widok EntryHandler jest mapowy Entry na następujące widoki natywne dla każdej platformy:

  • Katalizator systemu iOS/Mac: UITextField
  • Android: AppCompatEditText
  • Windows: TextBox

Na poniższych diagramach pokazano, jak Entry widok jest mapowany na widoki natywne za pośrednictwem elementu EntryHandler:

Architektura programu obsługi wprowadzania.

Maper Entry właściwości w EntryHandler klasie mapuje właściwości kontrolek międzyplatformowych na interfejs API widoku natywnego. Gwarantuje to, że po ustawieniu właściwości na Entryobiekcie podstawowy widok macierzysty jest aktualizowany zgodnie z potrzebami.

Maper właściwości można zmodyfikować w celu dostosowania Entry na każdej platformie:

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

W tym przykładzie Entry dostosowanie odbywa się w klasie strony. W związku z tym wszystkie Entry kontrolki w systemach Android, iOS i Windows zostaną dostosowane po utworzeniu wystąpienia.CustomizeEntryPage Dostosowywanie jest wykonywane przez uzyskanie dostępu do właściwości procedur PlatformView obsługi, która zapewnia dostęp do widoku natywnego mapowania na kontrolkę międzyplatformową na każdej platformie. Następnie kod natywny dostosowuje procedurę obsługi, zaznaczając cały tekst w Entry obiekcie, gdy zyskuje fokus.

Aby uzyskać więcej informacji na temat maperów, zobacz Mappers (Mapery).

Dostosowywanie określonego wystąpienia kontrolki

Programy obsługi są globalne, a dostosowywanie procedury obsługi dla kontrolki spowoduje dostosowanie wszystkich kontrolek tego samego typu w aplikacji. Jednak programy obsługi dla określonych wystąpień kontrolek można dostosować przez podklasę kontrolki, a następnie zmodyfikować program obsługi dla podstawowego typu kontrolki tylko wtedy, gdy kontrolka jest typu podklasy. Aby na przykład dostosować określoną Entry kontrolkę na stronie zawierającej wiele Entry kontrolek, należy najpierw podklasować kontrolkę Entry :

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

Następnie można dostosować element , za pomocą mapatora EntryHandlerwłaściwości, aby wykonać żądaną modyfikację tylko do MyEntry wystąpień:

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

Jeśli dostosowanie programu obsługi zostanie wykonane w klasie App , wszystkie MyEntry wystąpienia w aplikacji zostaną dostosowane zgodnie z modyfikacją programu obsługi.

Dostosowywanie kontrolki przy użyciu cyklu życia programu obsługi

Wszystkie procedury obsługi oparte na programie .NET MAUI steruje obsługą HandlerChanging i HandlerChanged zdarzeniami. Zdarzenie HandlerChanged jest zgłaszane, gdy widok natywny, który implementuje kontrolkę międzyplatformową, jest dostępny i inicjowany. Zdarzenie HandlerChanging jest zgłaszane, gdy program obsługi kontrolki ma zostać usunięty z kontrolki międzyplatformowej. Aby uzyskać więcej informacji na temat zdarzeń cyklu życia programu obsługi, zobacz Cykl życia programu obsługi.

Cykl życia programu obsługi może służyć do dostosowywania programu obsługi. Aby na przykład zasubskrybować i anulować subskrypcję, zdarzenia widoku natywnego należy zarejestrować programy obsługi zdarzeń dla HandlerChanged zdarzeń i HandlerChanging na dostosowanej kontrolce międzyplatformowej:

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

Programy obsługi można dostosować na platformę przy użyciu kompilacji warunkowej lub za pomocą klas częściowych do organizowania kodu w foldery i pliki specyficzne dla platformy. Każde podejście zostanie omówione z kolei przez dostosowanie Entry elementu tak, aby cały jego tekst został wybrany, gdy zyska fokus.

Kompilacja warunkowa

Plik za kodem zawierający programy obsługi zdarzeń dla HandlerChanged zdarzeń i HandlerChanging jest pokazany w poniższym przykładzie, który korzysta z kompilacji warunkowej:

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

Zdarzenie HandlerChanged jest wywoływane po utworzeniu i zainicjowaniu widoku natywnego, który implementuje kontrolkę międzyplatformową. W związku z tym program obsługi zdarzeń to miejsce, w którym powinny być wykonywane subskrypcje zdarzeń natywnych. Wymaga to rzutowania PlatformView właściwości programu obsługi na typ lub typ podstawowy widoku natywnego, aby można było uzyskać dostęp do zdarzeń natywnych. W tym przykładzie w systemach iOS, Mac Catalyst i Windows OnEntryHandlerChanged zdarzenie subskrybuje zdarzenia widoku natywnego, które są zgłaszane, gdy widoki natywne implementujące Entry fokus zysku.

Programy OnEditingDidBegin obsługi zdarzeń i OnGotFocus uzyskują dostęp do widoku natywnego dla odpowiednich Entry platform i wybierają cały tekst w obiekcie Entry.

Zdarzenie HandlerChanging jest wywoływane przed usunięciem istniejącego programu obsługi z kontrolki międzyplatformowej i przed utworzeniem nowej procedury obsługi dla kontrolki międzyplatformowej. W związku z tym jego program obsługi zdarzeń to miejsce, w którym należy usunąć subskrypcje zdarzeń natywnych, a inne oczyszczanie powinno zostać wykonane. Obiekt HandlerChangingEventArgs , który towarzyszy temu zdarzeniu, ma OldHandler właściwości i NewHandler , które zostaną ustawione odpowiednio na stare i nowe procedury obsługi. W tym przykładzie OnEntryHandlerChanging zdarzenie usuwa subskrypcję zdarzeń widoku natywnego w systemach iOS, Mac Catalyst i Windows.

Klasy częściowe

Zamiast korzystać z kompilacji warunkowej, można również używać klas częściowych do organizowania kodu dostosowywania kontrolek w folderach i plikach specyficznych dla platformy. Dzięki temu podejściu kod dostosowywania jest oddzielony od klasy częściowej międzyplatformowej i częściowej klasy specyficznej dla platformy:

  • Klasa częściowa międzyplatformowa zwykle definiuje elementy członkowskie, ale ich nie implementuje i jest tworzona dla wszystkich platform. Ta klasa nie powinna być umieszczana w żadnym folderze podrzędnym Platformy projektu, ponieważ uczyniłoby to klasą specyficzną dla platformy.
  • Klasa częściowa specyficzna dla platformy zwykle implementuje składowe zdefiniowane w klasie częściowej międzyplatformowej i jest tworzona dla jednej platformy. Ta klasa powinna zostać umieszczona w folderze podrzędnym folderu Platformy dla wybranej platformy.

W poniższym przykładzie przedstawiono międzyplatformową klasę częściową:

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

W tym przykładzie dwa programy obsługi zdarzeń nazywają metody częściowe o nazwie ChangedHandler i ChangingHandler, których podpisy są zdefiniowane w klasie częściowej międzyplatformowej. Implementacje metody częściowej są następnie definiowane w klasach częściowych specyficznych dla platformy, które powinny zostać umieszczone w odpowiednich folderach podrzędnych Platformy , aby upewnić się, że system kompilacji próbuje skompilować kod natywny tylko podczas kompilowania dla określonej platformy. Na przykład poniższy kod przedstawia klasę CustomizeEntryPartialMethodsPage w folderze Platformy>systemu Windows projektu:

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

Zaletą tego podejścia jest to, że kompilacja warunkowa nie jest wymagana i że metody częściowe nie muszą być implementowane na każdej platformie. Jeśli implementacja nie jest udostępniana na platformie, metoda i wszystkie wywołania metody zostaną usunięte w czasie kompilacji. Aby uzyskać informacje na temat metod częściowych, zobacz Metody częściowe.

Aby uzyskać informacje o organizacji folderu Platformy w projekcie .NET MAUI, zobacz Częściowe klasy i metody. Aby uzyskać informacje o sposobie konfigurowania wielowersyjności, aby nie trzeba było umieszczać kodu platformy w podfolderach folderu Platformy , zobacz Konfigurowanie wielowersyjności.