Настройка элементов управления с помощью обработчиков
Обработчики можно настроить для расширения внешнего вида и поведения кроссплатформенного элемента управления за пределами настройки, возможной с помощью API элемента управления. Эта настройка, которая изменяет собственные представления кроссплатформенного элемента управления, достигается путем изменения средства сопоставления для обработчика одним из следующих методов:
- PrependToMapping, который изменяет средство сопоставления обработчика перед применением сопоставлений элементов управления .NET MAUI.
- ModifyMapping, который изменяет существующее сопоставление.
- AppendToMapping, который изменяет средство сопоставления обработчика после применения сопоставлений элементов управления .NET MAUI.
Каждый из этих методов имеет идентичную сигнатуру, требующую двух аргументов:
- Ключ
string
на основе. При изменении одного из сопоставлений, предоставляемых .NET MAUI, необходимо указать ключ, используемый .NET MAUI. Ключевые значения, используемые сопоставлениями элементов управления .NET MAUI, основаны на именах интерфейсов и свойств, напримерnameof(IEntry.IsPassword)
. Интерфейсы и их свойства, которые абстрагируют каждый кроссплатформенный элемент управления, можно найти здесь. Это формат ключа, который следует использовать, если требуется, чтобы настройка обработчика выполнялось при каждом изменении свойства. В противном случае ключ может быть произвольным значением, которое не должно соответствовать имени свойства, предоставляемого типом. Например,MyCustomization
можно указать в качестве ключа любое изменение собственного представления, выполняемое в качестве настройки. Однако следствием этого формата ключа является то, что настройка обработчика будет выполняться только при первом изменении средства сопоставления обработчика. - Объект, Action представляющий метод, который выполняет настройку обработчика. Указывает Action два аргумента:
- Аргумент
handler
, предоставляющий экземпляр настраиваемого обработчика. - Аргумент
view
, предоставляющий экземпляр кроссплатформенного элемента управления, реализуемого обработчиком.
- Аргумент
Внимание
Настройки обработчика являются глобальными и не область в определенный экземпляр элемента управления. Настройка обработчика разрешена в любом месте приложения. После настройки обработчика все элементы управления этого типа влияют на все элементы управления этого типа везде в приложении.
Каждый класс обработчика предоставляет собственное представление кроссплатформенного элемента управления через его PlatformView свойство. К этому свойству можно получить доступ, чтобы задать свойства собственного представления, вызвать собственные методы представления и подписаться на события собственного представления. Кроме того, кроссплатформенный элемент управления, реализованный обработчиком, предоставляется через его VirtualView свойство.
Обработчики можно настроить на каждую платформу с помощью условной компиляции в многоцелевой код на основе платформы. Кроме того, можно использовать частичные классы для упорядочивания кода в папки и файлы для конкретной платформы. Дополнительные сведения об условной компиляции см. в разделе "Условная компиляция".
Настройка элемента управления
Представление .NET MAUI Entry — это элемент управления вводом текста с одной строкой, реализующий IEntry интерфейс. Представление EntryHandler сопоставляется Entry со следующими собственными представлениями для каждой платформы:
- IOS/Mac Catalyst:
UITextField
- Android:
AppCompatEditText
- Windows:
TextBox
На следующих схемах показано, как Entry представление сопоставляется с собственными представлениями с помощью EntryHandlerследующих схем:
Средство Entry сопоставления свойств в EntryHandler классе сопоставляет свойства кроссплатформенного элемента управления с API собственного представления. Это гарантирует, что при установке свойства в Entryбазовом собственном представлении обновляется по мере необходимости.
Сопоставление свойств можно изменить для настройки Entry на каждой платформе:
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
});
}
}
В этом примере настройка Entry выполняется в классе страницы. Поэтому все Entry элементы управления в Android, iOS и Windows будут настраиваться после создания экземпляра CustomizeEntryPage
. Настройка выполняется путем доступа к свойству обработчиков PlatformView , которое предоставляет доступ к собственному представлению, которое сопоставляется с кроссплатформенным элементом управления на каждой платформе. Затем машинный код настраивает обработчик, выбрав весь текст в фокусе Entry .
Дополнительные сведения о картах см. в разделе Mappers.
Настройка определенного экземпляра элемента управления
Обработчики являются глобальными, а настройка обработчика для элемента управления приведет к настройке всех элементов управления одного типа в приложении. Однако обработчики для конкретных экземпляров элементов управления можно настроить путем подкласса элемента управления, а затем путем изменения обработчика базового типа элемента управления только в том случае, если элемент управления имеет подклассный тип. Например, чтобы настроить определенный Entry элемент управления на странице, содержащей несколько Entry элементов управления, необходимо сначала подкласс элемента Entry управления:
namespace CustomizeHandlersDemo.Controls
{
internal class MyEntry : Entry
{
}
}
Затем можно настроить EntryHandler
mapper свойств с помощью схемы свойств, чтобы выполнить требуемое изменение только для MyEntry
экземпляров:
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
}
});
Если настройка обработчика выполняется в App
классе, все MyEntry
экземпляры в приложении будут настроены в соответствии с изменением обработчика.
Настройка элемента управления с помощью жизненного цикла обработчика
Все обработчики на основе .NET MAUI управляют поддержкой HandlerChanging и HandlerChanged событиями. Событие HandlerChanged возникает при использовании собственного представления, реализующего кроссплатформенный элемент управления, доступен и инициализирован. Событие HandlerChanging возникает, когда обработчик элемента управления будет удален из кроссплатформенного элемента управления. Дополнительные сведения о событиях жизненного цикла обработчика см. в разделе "Жизненный цикл обработчика".
Жизненный цикл обработчика можно использовать для настройки обработчика. Например, для подписки и отмены подписки на события собственного представления необходимо зарегистрировать обработчики событий для HandlerChanged HandlerChanging настраиваемого кроссплатформенного элемента управления:
<Entry HandlerChanged="OnEntryHandlerChanged"
HandlerChanging="OnEntryHandlerChanging" />
Обработчики можно настроить на каждую платформу с помощью условной компиляции или с помощью частичных классов для упорядочивания кода в папки и файлы для конкретной платформы. Каждый подход будет обсуждаться в свою очередь, настраивая Entry таким образом, чтобы все его текст был выбран при получении фокуса.
Условная компиляция
Файл кода программной части, содержащий обработчики событий для HandlerChanged событий, HandlerChanging показан в следующем примере, в котором используется условная компиляция:
#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
}
Событие HandlerChanged создается после создания и инициализации собственного представления, реализующего кроссплатформенный элемент управления. Поэтому его обработчик событий — это место, где должны выполняться собственные подписки на события. Для этого требуется приведение PlatformView свойства обработчика к типу или базовому типу собственного представления, чтобы получить доступ к собственным событиям. В этом примере в iOS, Mac Catalyst и Windows OnEntryHandlerChanged
событие подписывается на события собственного представления, возникающие при использовании собственных представлений Entry , реализующих фокус получения.
Обработчики OnEditingDidBegin
событий получают доступ к собственному представлению для Entry соответствующих платформ и выбирают весь текст, который находится в спискеEntry.OnGotFocus
Событие HandlerChanging возникает перед удалением существующего обработчика из кроссплатформенного элемента управления и перед созданием нового обработчика для кроссплатформенного элемента управления. Таким образом, его обработчик событий заключается в том, что собственные подписки на события должны быть удалены, а другая очистка должна выполняться. Объект HandlerChangingEventArgs , сопровождающий это событие, имеет OldHandler и NewHandler свойства, которые будут заданы для старых и новых обработчиков соответственно. В этом примере OnEntryHandlerChanging
событие удаляет подписку на события собственного представления в iOS, Mac Catalyst и Windows.
Разделяемые классы
Вместо использования условной компиляции можно также использовать частичные классы для упорядочивания кода настройки элемента управления в папки и файлы для конкретной платформы. При таком подходе код настройки разделен на кроссплатформенный частичный класс и частичный класс для конкретной платформы:
- Кроссплатформенный частичный класс обычно определяет элементы, но не реализует их и строится для всех платформ. Этот класс не должен размещаться в дочерних папках проекта Platform , так как это позволит сделать его классом, зависящим от платформы.
- Разделяемый класс, зависящий от платформы, обычно реализует члены, определенные в кроссплатформенных частичных классах, и создается для одной платформы. Этот класс должен быть помещен в дочернюю папку папки 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);
}
В этом примере два обработчика событий вызывают частичные методы с именем ChangedHandler
и ChangingHandler
сигнатуры которого определяются в кроссплатформенных частичных классах. Затем реализации частичных методов определяются в разделяемых классах для конкретной платформы, которые должны быть помещены в правильные дочерние папки Платформ , чтобы гарантировать, что система сборки пытается создать собственный код только при создании конкретной платформы. Например, в следующем коде показан CustomizeEntryPartialMethodsPage
класс в папке "Платформы>Windows" проекта:
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();
}
}
}
Преимущество этого подхода заключается в том, что условная компиляция не требуется, и что частичные методы не должны быть реализованы на каждой платформе. Если реализация не предоставляется на платформе, метод и все вызовы метода удаляются во время компиляции. Сведения о частичных методах см. в разделе "Частичные методы".
Сведения о организации папки "Платформы " в проекте .NET MAUI см. в разделе "Частичные классы и методы". Сведения о настройке нескольких целевых объектов для размещения кода платформы в вложенных папках папки "Платформы " см. в разделе "Настройка нескольких целевых объектов".