Migrace vlastního rendereru Xamarin.Forms do obslužné rutiny .NET MAUI
V Xamarin.Forms se vlastní renderery dají použít k přizpůsobení vzhledu a chování ovládacího prvku a vytvoření nových ovládacích prvků pro různé platformy. Každý vlastní renderer má odkaz na řízení napříč platformami a často spoléhá na INotifyPropertyChanged
odesílání oznámení o změnách vlastností. Místo použití vlastních rendererů představuje uživatelské rozhraní .NET Multi-Platform App UI (.NET MAUI) nový koncept označovaný jako obslužná rutina.
Obslužné rutiny nabízejí mnoho vylepšení výkonu u vlastních rendererů. V Xamarin.Forms třída ViewRenderer
vytvoří nadřazený prvek. Například v Androidu se vytvoří objekt ViewGroup
, který se používá pro pomocné úlohy umístění. V rozhraní .NET MAUI ViewHandler
třída nevytvoří nadřazený prvek, což pomáhá snížit velikost hierarchie vizuálů a zlepšit výkon vaší aplikace. Obslužné rutiny také oddělí ovládací prvky platformy od architektury. Řízení platformy musí zpracovávat pouze potřeby architektury. To je nejen efektivnější, ale v případě potřeby je mnohem jednodušší rozšířit nebo přepsat. Obslužné rutiny jsou také vhodné pro opakované použití jinými architekturami, jako jsou kometa a Báječná. Další informace o obslužných rutinách naleznete v tématu Obslužné rutiny.
V Xamarin.Forms OnElementChanged
metoda ve vlastním rendereru vytvoří ovládací prvek platformy, inicializuje výchozí hodnoty, přihlásí se k odběru událostí a zpracuje prvek Xamarin.Forms, ke kterému byl renderer připojen (OldElement
) a element, ke kterému je renderer připojený (NewElement
). Kromě toho jedna OnElementPropertyChanged
metoda definuje operace, které se mají vyvolat, když dojde ke změně vlastnosti v ovládacím prvku pro různé platformy. .NET MAUI tento přístup zjednodušuje, takže každá změna vlastností je zpracována samostatnou metodou, a proto je kód pro vytvoření ovládacího prvku platformy, provedení nastavení ovládacího prvku a vyčištění ovládacího prvku oddělen do odlišných metod.
Proces migrace vlastního ovládacího prvku Xamarin.Forms, který je založen na vlastních rendererech na každé platformě na vlastní ovládací prvek .NET MAUI, který je založen na obslužné rutině na každé platformě, je následující:
- Vytvořte třídu pro multiplatformní řízení, která poskytuje veřejné rozhraní API ovládacího prvku. Další informace najdete v tématu Vytvoření víceplatformového ovládacího prvku.
- Vytvořte
partial
třídu obslužné rutiny. Další informace naleznete v tématu Vytvoření obslužné rutiny. - Ve třídě obslužné rutiny vytvořte
PropertyMapper
slovník, který definuje akce, které se mají provést při změně vlastností pro různé platformy. Další informace naleznete v tématu Vytvoření mapovače vlastností. - Vytvořte
partial
třídy obslužné rutiny pro každou platformu, která vytváří nativní zobrazení, která implementují řízení napříč platformami. Další informace najdete v tématu Vytvoření ovládacích prvků platformy. - Zaregistrujte obslužnou rutinu pomocí
ConfigureMauiHandlers
metod aAddHandler
metod ve třídě vaší aplikaceMauiProgram
. Další informace naleznete v tématu Registrace obslužné rutiny.
Pak je možné využívat řízení napříč platformami. Další informace najdete v tématu Využití řízení napříč platformami.
Alternativně lze vlastní renderery, které přizpůsobí ovládací prvky Xamarin.Forms, převést tak, aby upravovaly obslužné rutiny .NET MAUI. Další informace naleznete v tématu Přizpůsobení ovládacích prvků pomocí obslužných rutin.
Vytvoření ovládacího prvku pro různé platformy
Pokud chcete vytvořit ovládací prvek pro různé platformy, měli byste vytvořit třídu odvozenou z View:
namespace MyMauiControl.Controls
{
public class CustomEntry : View
{
public static readonly BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(CustomEntry), null);
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create(nameof(TextColor), typeof(Color), typeof(CustomEntry), null);
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public Color TextColor
{
get { return (Color)GetValue(TextColorProperty); }
set { SetValue(TextColorProperty, value); }
}
}
}
Ovládací prvek by měl poskytovat veřejné rozhraní API, ke kterému bude přistupovat jeho obslužná rutina, a řídit uživatele. Ovládací prvky napříč platformami by měly být odvozeny od View, který představuje vizuální prvek, který se používá k umístění rozložení a zobrazení na obrazovce.
Vytvoření obslužné rutiny
Po vytvoření řízení napříč platformami byste měli vytvořit třídu pro obslužnou rutinu partial
:
#if IOS || MACCATALYST
using PlatformView = Microsoft.Maui.Platform.MauiTextField;
#elif ANDROID
using PlatformView = AndroidX.AppCompat.Widget.AppCompatEditText;
#elif WINDOWS
using PlatformView = Microsoft.UI.Xaml.Controls.TextBox;
#elif (NETSTANDARD || !PLATFORM) || (NET6_0_OR_GREATER && !IOS && !ANDROID)
using PlatformView = System.Object;
#endif
using MyMauiControl.Controls;
using Microsoft.Maui.Handlers;
namespace MyMauiControl.Handlers
{
public partial class CustomEntryHandler
{
}
}
Třída obslužné rutiny je částečná třída, jejíž implementace bude dokončena na každé platformě s další částečnou třídou.
Podmíněné using
příkazy definují PlatformView
typ na každé platformě. Konečný podmíněný using
příkaz definuje PlatformView
, že se System.Object
rovná . To je nezbytné, aby se PlatformView
typ mohl použít v rámci obslužné rutiny pro použití na všech platformách. Alternativou by bylo definovat vlastnost jednou pro každou platformu PlatformView
pomocí podmíněné kompilace.
Vytvoření mapovače vlastností
Každá obslužná rutina obvykle poskytuje mapovač vlastností, který definuje, jaké akce se mají provést, když dojde ke změně vlastnosti v ovládacím prvku pro různé platformy. Typ PropertyMapper
je typ Dictionary
, který mapuje vlastnosti ovládacího prvku pro různé platformy na přidružené akce.
Poznámka:
Mapovač vlastností je náhradou za metodu OnElementPropertyChanged
ve vlastním rendereru Xamarin.Forms.
PropertyMapper
je definován v obecné ViewHandler
třídě .NET MAUI a vyžaduje, aby byly zadány dva obecné argumenty:
- Třída pro řízení napříč platformami, která je odvozena od View.
- Třída obslužné rutiny.
Následující příklad kódu ukazuje CustomEntryHandler
třídu rozšířenou o definici PropertyMapper
:
public partial class CustomEntryHandler
{
public static PropertyMapper<CustomEntry, CustomEntryHandler> PropertyMapper = new PropertyMapper<CustomEntry, CustomEntryHandler>(ViewHandler.ViewMapper)
{
[nameof(CustomEntry.Text)] = MapText,
[nameof(CustomEntry.TextColor)] = MapTextColor
};
public CustomEntryHandler() : base(PropertyMapper)
{
}
}
Jedná PropertyMapper
se o Dictionary
klíč, jehož klíč je string
a jehož hodnota je obecný Action
. Představuje string
název vlastnosti ovládacího prvku pro různé platformy a Action
představuje metodu static
, která vyžaduje obslužnou rutinu a řízení mezi platformami jako argumenty. Například podpis MapText
metody je public static void MapText(CustomEntryHandler handler, CustomEntry view)
.
Každá obslužná rutina platformy musí poskytovat implementace akcí, které manipulují s rozhraními API nativního zobrazení. Tím se zajistí, že když je vlastnost nastavena v ovládacím prvku pro různé platformy, podkladové nativní zobrazení se podle potřeby aktualizuje. Výhodou tohoto přístupu je, že umožňuje snadné přizpůsobení řízení napříč platformami, protože mapovač vlastností může být upraven spotřebiteli řízení napříč platformami bez podtřídy. Další informace naleznete v tématu Přizpůsobení ovládacích prvků pomocí obslužných rutin.
Vytvoření ovládacích prvků platformy
Po vytvoření mapovačů pro obslužnou rutinu musíte poskytnout implementace obslužné rutiny na všech platformách. Toho lze dosáhnout přidáním dílčích implementací obslužné rutiny tříd do podřízených složek složky Platformy . Případně můžete projekt nakonfigurovat tak, aby podporoval cílení na více názvů souborů nebo více cílení na složky nebo obojí.
Cílení na více názvů souborů je nakonfigurováno přidáním následujícího KÓDU XML do souboru projektu jako podřízených položek <Project>
uzlu:
<!-- Android -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-android')) != true">
<Compile Remove="**\*.Android.cs" />
<None Include="**\*.Android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<!-- iOS and Mac Catalyst -->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true AND $(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
<Compile Remove="**\*.MaciOS.cs" />
<None Include="**\*.MaciOS.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<!-- Windows -->
<ItemGroup Condition="$(TargetFramework.Contains('-windows')) != true ">
<Compile Remove="**\*.Windows.cs" />
<None Include="**\*.Windows.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
Další informace o konfiguraci cílení na více verzí najdete v tématu Konfigurace cílení na více verzí.
Každá třída obslužné rutiny platformy by měla být částečnou třídou a odvozena od obecné ViewHandler
třídy, která vyžaduje dva argumenty typu:
- Třída pro řízení napříč platformami, která je odvozena od View.
- Typ nativního zobrazení, který implementuje multiplatformní řízení na platformě. To by mělo být stejné jako typ
PlatformView
vlastnosti v obslužné rutině.
Důležité
Třída ViewHandler
poskytuje VirtualView
a PlatformView
vlastnosti. Vlastnost VirtualView
se používá pro přístup k ovládacímu prvku pro různé platformy z jeho obslužné rutiny. Tato PlatformView
vlastnost se používá pro přístup k nativnímu zobrazení na každé platformě, která implementuje řízení napříč platformami.
Každá implementace obslužné rutiny platformy by měla přepsat následující metody:
CreatePlatformView
, který by měl vytvořit a vrátit nativní zobrazení, které implementuje řízení napříč platformami.ConnectHandler
, který by měl provést jakékoli nastavení nativního zobrazení, jako je inicializace nativního zobrazení a provádění odběrů událostí.DisconnectHandler
, který by měl provést jakékoli nativní vyčištění zobrazení, jako je například zrušení odběru událostí a odstraňování objektů. Tato metoda není záměrně vyvolána rozhraním .NET MAUI. Místo toho ho musíte vyvolat sami z vhodného umístění v životním cyklu vaší aplikace. Další informace naleznete v tématu Nativní vyčištění zobrazení.
Poznámka:
, CreatePlatformView
ConnectHandler
a DisconnectHandler
přepsání jsou nahrazení metody OnElementChanged
ve vlastním rendereru Xamarin.Forms.
Každá obslužná rutina platformy by také měla implementovat akce definované ve slovníkech mapperu. Kromě toho by každá obslužná rutina platformy měla také poskytnout kód, jak je potřeba, aby implementovaly funkce řízení napříč platformami na platformě. Pro složitější ovládací prvky, které lze poskytnout dalším typem.
Následující příklad ukazuje implementaci v Androidu CustomEntryHandler
:
#nullable enable
using AndroidX.AppCompat.Widget;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using MyMauiControl.Controls;
namespace MyMauiControl.Handlers
{
public partial class CustomEntryHandler : ViewHandler<CustomEntry, AppCompatEditText>
{
protected override AppCompatEditText CreatePlatformView() => new AppCompatEditText(Context);
protected override void ConnectHandler(AppCompatEditText platformView)
{
base.ConnectHandler(platformView);
// Perform any control setup here
}
protected override void DisconnectHandler(AppCompatEditText platformView)
{
// Perform any native view cleanup here
platformView.Dispose();
base.DisconnectHandler(platformView);
}
public static void MapText(CustomEntryHandler handler, CustomEntry view)
{
handler.PlatformView.Text = view.Text;
handler.PlatformView?.SetSelection(handler.PlatformView?.Text?.Length ?? 0);
}
public static void MapTextColor(CustomEntryHandler handler, CustomEntry view)
{
handler.PlatformView?.SetTextColor(view.TextColor.ToPlatform());
}
}
}
CustomEntryHandler
odvozuje z ViewHandler
třídy, s obecným CustomEntry
argumentem určujícím typ ovládacího prvku pro různé platformy a AppCompatEditText
argument určující typ nativního ovládacího prvku.
Přepsání CreatePlatformView
vytvoří a vrátí AppCompatEditText
objekt. Přepsání ConnectHandler
je umístění pro provedení požadovaného nastavení nativního zobrazení. Přepsání DisconnectHandler
je umístění pro provedení nativního čištění zobrazení, a proto volá metodu Dispose
v AppCompatEditText
instanci.
Obslužná rutina také implementuje Akce definované ve slovníku mapper vlastnosti. Každá akce se provádí v reakci na vlastnost, která se mění v ovládacím prvku pro různé platformy, a je metoda, která vyžaduje obslužnou static
rutinu a instance řízení napříč platformami jako argumenty. V každém případě akce volá metody definované v nativním ovládacím prvku.
Registrace obslužné rutiny
Před použitím vlastního ovládacího prvku a jeho obslužné rutiny musí být registrovány v aplikaci. K tomu by mělo dojít v CreateMauiApp
metodě ve MauiProgram
třídě v projektu aplikace, což je vstupní bod aplikace pro různé platformy:
using Microsoft.Extensions.Logging;
using MyMauiControl.Controls;
using MyMauiControl.Handlers;
namespace MyMauiControl;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler(typeof(CustomEntry), typeof(CustomEntryHandler));
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
Obslužná rutina je zaregistrována pomocí ConfigureMauiHandlers
metody a AddHandler
metody. Prvním argumentem AddHandler
metody je typ ovládacího prvku pro různé platformy, přičemž druhým argumentem je jeho typ obslužné rutiny.
Poznámka:
Tento přístup registrace zabraňuje skenování sestavení Xamarin.Forms, což je pomalé a nákladné.
Využívání multiplatformních ovládacích prvků
Po registraci obslužné rutiny ve vaší aplikaci se pak dá využívat řízení mezi platformami:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyMauiControl.Controls"
x:Class="MyMauiControl.MainPage">
<Grid>
<controls:CustomEntry Text="Hello world"
TextColor="Blue" />
</Grid>
</ContentPage>
Vyčištění nativního zobrazení
Implementace obslužné rutiny DisconnectHandler
každé platformy přepíše implementaci, která se používá k provádění nativního čištění zobrazení, jako je zrušení odběru událostí a odstraňování objektů. Toto přepsání však záměrně nevyvolává rozhraní .NET MAUI. Místo toho ho musíte vyvolat sami z vhodného umístění v životním cyklu vaší aplikace. To může být v případě, že stránka obsahující ovládací prvek přejde pryč, což způsobí vyvolání události stránky Unloaded
.
Obslužnou rutinu události pro událost stránky Unloaded
je možné zaregistrovat v XAML:
<ContentPage ...
xmlns:controls="clr-namespace:MyMauiControl.Controls"
Unloaded="ContentPage_Unloaded">
<Grid>
<controls:CustomEntry x:Name="customEntry"
... />
</Grid>
</ContentPage>
Obslužná rutina události události Unloaded
pak může vyvolat metodu DisconnectHandler
ve své Handler
instanci:
void ContentPage_Unloaded(object sender, EventArgs e)
{
customEntry.Handler?.DisconnectHandler();
}
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro