처리기를 사용하여 .NET MAUI 컨트롤 사용자 지정

.NET 다중 플랫폼 앱 UI(.NET MAUI)는 데이터를 표시하고, 작업을 시작하고, 활동을 나타내고, 컬렉션을 표시하고, 데이터를 선택하는 데 사용할 수 있는 컨트롤 컬렉션을 제공합니다. 각 컨트롤에는 컨트롤을 추상화하는 인터페이스 표현이 있습니다. 이러한 인터페이스를 구현하는 플랫폼 간 컨트롤을 가상 보기라고 합니다. 처리기는 이러한 가상 보기를 각 플랫폼의 네이티브 컨트롤에 매핑하고 기본 네이티브 컨트롤을 만들고 해당 속성을 플랫폼 간 컨트롤에 매핑하는 작업을 담당합니다. 예를 들어 iOS .NET MAUI 처리기는 .NET MAUI Button 를 iOS UIButton 컨트롤에 매핑합니다. Android Button 컨트롤에 AppCompatButton 매핑됩니다.

Button handler architecture.

Handlers are accessed through their control-specific interface, such as IButton for a Button. 이렇게 하면 플랫폼 간 컨트롤이 해당 처리기를 참조해야 하고 처리기가 플랫폼 간 컨트롤을 참조하지 않아도 됩니다. 각 처리기는 플랫폼 간 컨트롤 API를 네이티브 컨트롤 API에 매핑하는 매퍼 를 제공합니다.

처리기를 사용자 지정하여 컨트롤의 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 뷰를 구현하는 형식 이름 목록은 처리기 기반 보기를 참조하세요.

매퍼를 사용하여 컨트롤 사용자 지정

.NET MAUI Entry 는 인터페이스를 구현하는 한 줄 텍스트 입력 컨트롤입니다 IEntry . iOS iOS EntryHandler 컨트롤에 UITextField 매핑 Entry 됩니다. Android Entry 컨트롤에 AppCompatEditText 매핑되고 Windows Entry 컨트롤에 TextBox 매핑됩니다.

Entry handler architecture.

클래스의 EntryHandler 매퍼는 Entry 플랫폼 간 컨트롤 API를 네이티브 컨트롤 API에 매핑합니다. 이 매퍼는 각 플랫폼에서 컨트롤을 사용자 지정하도록 수정할 수 있습니다.

using Microsoft.Maui.Platform;

namespace CustomizeHandlersDemo;

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

        ModifyEntry();
    }

    void ModifyEntry()
    {
        Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
        {
#if ANDROID
            handler.PlatformView.SetBackgroundColor(Colors.Transparent.ToPlatform());
#elif iOS
            handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
#elif WINDOWS
            handler.PlatformView.FontWeight = Microsoft.UI.Text.FontWeights.Thin;
#endif
        });
    }
}

이 예제에서는 Entry 페이지 클래스에서 사용자 지정이 수행됩니다. 따라서 인스턴스가 만들어지면 Android, iOS 및 Windows 대한 모든 Entry 컨트롤이 CustomizeEntryPage 사용자 지정됩니다. 다음 사용자 지정은 컴파일러 전처리 지시문을 사용하여 수행됩니다.

  • Android 배경색 Entry 이 투명하게 설정됩니다.
  • iOS 테두리가 제거Entry됩니다.
  • Windows 글꼴 Entry 두께가 얇게 설정됩니다.

특정 컨트롤 인스턴스 사용자 지정

처리기는 전역이며 컨트롤에 대한 처리기를 사용자 지정하면 앱에서 동일한 형식의 모든 컨트롤이 사용자 지정됩니다. 그러나 컨트롤을 서브클래싱한 다음 컨트롤이 서브클래싱된 형식인 경우에만 기본 컨트롤 형식에 대한 처리기를 수정하여 특정 컨트롤 인스턴스에 대한 처리기를 사용자 지정할 수 있습니다. 예를 들어 여러 Entry 컨트롤이 포함된 페이지에서 특정 Entry 컨트롤을 사용자 지정하려면 먼저 컨트롤을 Entry 서브클래스해야 합니다.

namespace CustomizeHandlersDemo;

public class MyEntry : Entry
{
}

그런 다음, 매퍼를 EntryHandler통해 사용자 지정하여 원하는 인스턴스 수정을 MyEntry 수행할 수 있습니다.

Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(IView.Background), (handler, view) =>
{
    if (view is MyEntry)
    {
#if ANDROID
        handler.PlatformView.SetBackgroundColor(Colors.Red.ToPlatform());
#elif IOS
        handler.PlatformView.BackgroundColor = Colors.Red.ToPlatform();
        handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.Line;
#elif WINDOWS
        handler.PlatformView.Background = Colors.Red.ToPlatform();
#endif
    }
});

그러면 처리기 수정에 따라 앱의 모든 MyEntry 인스턴스가 사용자 지정됩니다.

처리기 수명 주기

모든 처리기 기반 .NET MAUI 컨트롤은 두 개의 처리기 수명 주기 이벤트를 지원합니다.

  • HandlerChanging 는 플랫폼 간 컨트롤에 대해 새 처리기를 만들려는 경우와 플랫폼 간 컨트롤에서 기존 처리기를 제거하려고 할 때 발생합니다. HandlerChangingEventArgs 이 이벤트 NewHandler 와 함께 제공되는 개체에는 형식IElementHandler의 속성이 있습니다OldHandler. 속성이 NewHandler 아닌 null경우 이벤트는 플랫폼 간 컨트롤에 대한 새 처리기를 만들 예정임을 나타냅니다. 속성이 OldHandler 아닌 null경우 이벤트는 기존 네이티브 컨트롤이 플랫폼 간 컨트롤에서 제거될 예정임을 나타내므로 네이티브 이벤트를 배선 해제하고 기타 정리를 수행해야 합니다.
  • HandlerChanged 는 플랫폼 간 컨트롤에 대한 처리기를 만든 후에 발생합니다. 이 이벤트는 플랫폼 간 컨트롤을 구현하는 네이티브 컨트롤을 사용할 수 있으며 플랫폼 간 컨트롤에 설정된 모든 속성 값이 네이티브 컨트롤에 적용되었음을 나타냅니다.

참고

이벤트는 HandlerChanging 이벤트 전에 플랫폼 간 컨트롤에서 발생합니다 HandlerChanged .

이러한 이벤트 외에도 각 플랫폼 간 컨트롤에는 이벤트가 발생할 때 HandlerChanged 호출되는 재정의 가능한 OnHandlerChanged 메서드와 OnHandlerChanging 이벤트가 발생할 때 HandlerChanging 호출되는 메서드도 있습니다.

네이티브 컨트롤 이벤트 구독

처리기 속성에 PlatformView 액세스하여 네이티브 컨트롤 속성을 설정하고, 네이티브 컨트롤 메서드를 호출하고, 네이티브 컨트롤 이벤트를 구독할 수 있습니다. 네이티브 컨트롤 이벤트 구독은 이벤트가 발생할 때 HandlerChanged 발생해야 합니다. 이는 플랫폼 간 컨트롤을 구현하는 네이티브 컨트롤을 사용할 수 있고 초기화됨을 나타냅니다. 마찬가지로 네이티브 이벤트에서 구독 취소는 이벤트가 발생할 때 HandlerChanging 발생해야 합니다. 이는 컨트롤의 처리기가 플랫폼 간 컨트롤에서 제거될 것임을 나타냅니다. 처리기 수명 주기 이벤트에 대한 자세한 내용은 처리기 수명 주기를 참조하세요.

네이티브 컨트롤 이벤트를 구독하고 구독을 취소하려면 사용자 지정되는 플랫폼 간 컨트롤의 HandlerChanged 이벤트 및 HandlerChanging 이벤트 처리기를 등록해야 합니다.

<Entry HandlerChanged="OnHandlerChanged"
       HandlerChanging="OnHandlerChanging" />

컴파일러 전처리기 지시문을 사용하거나 부분 클래스를 사용하여 코드를 플랫폼별 폴더 및 파일로 구성하여 플랫폼별로 처리기를 사용자 지정할 수 있습니다. 각 방법은 Android 사용자 지정하여 Entry 차례로 설명합니다.

전처리기 지시문 사용

전처리기 지시문을 사용하는 다음 예제에서는 이벤트 및 HandlerChanging 이벤트에 대한 HandlerChanged 이벤트 처리기를 포함하는 코드 숨김 파일을 보여 줍니다.

using Microsoft.Maui.Platform;

namespace CustomizeHandlersDemo;

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

    void OnHandlerChanged(object sender, EventArgs e)
    {
#if ANDROID
        ((sender as Entry).Handler.PlatformView as Android.Views.View).FocusChange += OnFocusChange;
#endif
    }

    void OnHandlerChanging(object sender, HandlerChangingEventArgs e)
    {
        if (e.OldHandler != null)
        {
#if ANDROID
            (e.OldHandler.PlatformView as Android.Views.View).FocusChange -= OnFocusChange;
#endif
        }
    }

#if ANDROID
    void OnFocusChange(object sender, EventArgs e)
    {
        var nativeView = sender as AndroidX.AppCompat.Widget.AppCompatEditText;

        if (nativeView.IsFocused)
            nativeView.SetBackgroundColor(Colors.LightPink.ToPlatform());
        else
            nativeView.SetBackgroundColor(Colors.Transparent.ToPlatform());
    }
#endif        
}

HandlerChanged 이벤트는 플랫폼 간 컨트롤을 구현하는 네이티브 컨트롤을 만들고 초기화한 후에 발생합니다. 따라서 해당 이벤트 처리기는 네이티브 이벤트 구독을 수행해야 하는 위치입니다. 이렇게 하려면 네이티브 이벤트에 액세스할 수 있도록 처리기의 속성을 네이티브 컨트롤의 형식 또는 기본 형식으로 캐스팅 PlatformView 해야 합니다. 이 예제에서 이벤트는 네이 OnHandlerChanged 티브 컨트롤의 FocusChange 이벤트를 구독합니다.

OnFocusChange 이벤트 처리기는 컨트롤이 포커스를 얻고 손실될 때 기본 컨트롤에 Entry 액세스하고 배경색을 설정합니다.

HandlerChanging 이벤트는 플랫폼 간 컨트롤에서 기존 처리기가 제거되기 전과 플랫폼 간 컨트롤에 대한 새 처리기가 생성되기 전에 발생합니다. 따라서 해당 이벤트 처리기는 네이티브 이벤트 구독을 제거해야 하는 위치이며 다른 정리를 수행해야 합니다. HandlerChangingEventArgs 이 이벤트와 함께 제공되는 개체에는 OldHandler 각각 이전 및 NewHandler 새 처리기로 설정되는 속성이 있습니다. 이 예제에서 이벤트는 네이 OnHandlerChanging 티브 FocusChange 이벤트에 대한 구독을 제거합니다.

partial 클래스 사용

컴파일러 전처리기 지시문을 사용하여 앱을 조건부로 컴파일하는 대신 부분 클래스를 사용하여 컨트롤 사용자 지정 코드를 플랫폼별 폴더 및 파일로 구성할 수도 있습니다. 이 방법을 사용하면 사용자 지정 코드가 플랫폼 간 부분 클래스 및 플랫폼별 partial 클래스로 구분됩니다. 다음 예제에서는 플랫폼 간 부분 클래스를 보여줍니다.

namespace CustomizeHandlersDemo;

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

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

    void OnHandlerChanged(object sender, EventArgs e) => ChangedHandler(sender, e);

    void OnHandlerChanging(object sender, HandlerChangingEventArgs e) => ChangingHandler(sender, e);
}

이 예제에서 두 이벤트 처리기는 이름이 지정된 ChangedHandler 부분 메서드를 호출하고 ChangingHandler, 해당 시그니처는 플랫폼 간 partial 클래스에 정의됩니다. 부분 메서드 구현은 프로젝트의 Platforms>Android 폴더에 있는 플랫폼별 partial 클래스에 정의됩니다.

using Microsoft.Maui.Platform;

namespace CustomizeHandlersDemo;

public partial class CustomizeEntryPage : ContentPage
{
    partial void ChangedHandler(object sender, EventArgs e)
    {
        ((sender as Entry).Handler.PlatformView as Android.Views.View).FocusChange += OnFocusChange;
    }

    partial void ChangingHandler(object sender, HandlerChangingEventArgs e)
    {
        if (e.OldHandler != null)
        {
            (e.OldHandler.PlatformView as Android.Views.View).FocusChange -= OnFocusChange;
        }
    }

    void OnFocusChange(object sender, EventArgs e)
    {
        var nativeView = sender as AndroidX.AppCompat.Widget.AppCompatEditText;

        if (nativeView.IsFocused)
        {
            nativeView.SetBackgroundColor(Colors.LightPink.ToPlatform());
        }
        else
        {
            nativeView.SetBackgroundColor(Colors.Transparent.ToPlatform());
        }
    }
}

이 방법의 장점은 컴파일러 전처리 지시문이 필요하지 않으며 부분 메서드를 각 플랫폼에서 구현할 필요가 없다는 것입니다. 구현이 플랫폼에서 제공되지 않으면 컴파일 시간에 메서드와 메서드에 대한 모든 호출이 제거됩니다. 부분 메서드에 대한 자세한 내용은 Partial 메서드를 참조하세요.

처리기 기반 뷰

다음 표에서는 .NET MAUI에서 처리기 기반 뷰를 구현하는 형식을 나열합니다.

보기 인터페이스 Handler Mapper
ActivityIndicator IActivityIndicator ActivityIndicatorHandler Mapper
BlazorWebView IBlazorWebView BlazorWebViewHandler BlazorWebViewMapper
Border IBorderView BorderHandler Mapper
Button IButton ButtonHandler Mapper
CarouselView CarouselViewHandler Mapper
CheckBox ICheckBox CheckBoxHandler Mapper
CollectionView CollectionViewHandler Mapper
ContentView IContentView ContentViewHandler Mapper
DatePicker IDatePicker DatePickerHandler Mapper
Editor IEditor EditorHandler Mapper
Ellipse ShapeViewHandler Mapper
Entry IEntry EntryHandler Mapper
GraphicsView IGraphicsView GraphicsViewHandler Mapper
Image IImage ImageHandler Mapper
ImageButton IImageButton ImageButtonHandler Mapper
IndicatorView IIndicatorView IndicatorViewHandler Mapper
Label ILabel LabelHandler Mapper
Line LineHandler Mapper
Path PathHandler Mapper
Picker IPicker PickerHandler Mapper
Polygon PolygonHandler Mapper
Polyline PolylineHandler Mapper
ProgressBar IProgress ProgressBarHandler Mapper
RadioButton IRadioButton RadioButtonHandler Mapper
Rectangle RectangleHandler Mapper
RefreshView IRefreshView RefreshViewHandler Mapper
RoundRectangle RoundRectangleHandler Mapper
ScrollView IScrollView ScrollViewHandler Mapper
SearchBar ISearchBar SearchBarHandler Mapper
Slider ISlider SliderHandler Mapper
Stepper IStepper StepperHandler Mapper
SwipeView ISwipeView SwipeViewHandler Mapper
Switch ISwitch SwitchHandler Mapper
TimePicker ITimePicker TimePickerHandler Mapper
WebView IWebView WebViewHandler Mapper

모든 처리기는 다음 예외를 Microsoft.Maui.Handlers 제외하고 네임스페이스에 있습니다.

  • CarouselViewHandlerCollectionViewHandler 임스페이스에 Microsoft.Maui.Controls.Handlers.Items 있습니다.
  • LineHandler, PathHandler, PolygonHandler, PolylineHandlerRectangleHandlerRoundRectangleHandler 네임스페이스에 Microsoft.Maui.Controls.Handlers 있습니다.

위의 표에 있는 인터페이스는 네임스페이스에 Microsoft.Maui 있습니다.

렌더러 기반 보기

다음 레거시 Xamarin.Forms 뷰는 처리기가 아닌 렌더러에서 지원되며 다른 사용자 지정 방법을 사용합니다.

  • BoxView
  • Frame
  • ListView
  • TableView