Обработчики настраиваемых элементов управления .net maui, как преобразовать содержимое между виртуальным представлением и представлением платформы

Я пытаюсь создать собственный обработчик Maui для WinUI3 NavigationView.

Я определил отображение из виртуального представления в PlatformView, но я не могу преобразовать содержимое виртуального представления в содержимое PlatformView,

Например, у меня есть NavigationView.Content = Microsoft.Maui.Frame.Content.

Просматривая код maui, кажется, что есть несколько картографов, но я не могу понять, как их вызвать.

Вот мой текущий код

      public static void MapContent(IZtNavigationViewHandler viewHandler, IZtNavigationView virtualView) 
{ 
  ((NavigationView)(viewHandler?.PlatformView)).Content = virtualView.Content; 
}

Mapper вызывается, но он не может правильно преобразовать содержимое

Любые идеи или указатели?

1 ответ

TL;DR Строки в написанном от руки методе сопоставления пользовательского обработчика, где сопоставляется содержимое:

          if (handler.VirtualView.PresentedContent is IView view) 
        handler.PlatformView.Children.Add(view.ToPlatform(handler.MauiContext));

ИЛИ, если у PlatformView есть свойство Content (у NavigationView есть), то:

          if (handler.VirtualView.PresentedContent is IView view) 
        handler.PlatformView.Content = view.ToPlatform(handler.MauiContext);

Подход 3 будет использовать этот синтаксис.


Первый, Frame, ListView, а также TableViewявляются «устаревшими» представлениями на основе Renderer . Они не используют обработчики.

Не используйте ни один из них.

Пытаться ContentViewкак виртуальный вид.
В источнике Мауи, ContentViewHandler.Windows.csявляется поведением по умолчанию.


Данный:

      public class MyContentView : ContentView
{
}

Цель состоит в том, чтобы создать обработчик, который сопоставляет MyContentView с NavigationView WinUI3 и MyContentView.Content с NavigationView.Content.


АЛЬТЕРНАТИВА 1 — MyContentViewHandler

Аналогично настройке конкретных экземпляров элементов управления и аналогично
исходному решению Maui «Microsoft.Maui» /Controls/samples/Maui.Controls.Sample/Controls/BordelessEntry/BordelessEntryHandler.cs.

Одно существенное отличие: вместо прямого сопоставления с NavigationView позвольте MyContentView создать ContentPanel (логика, унаследованная от ContentViewHandler), а затем сделайте NavigationView дочерним элементом ContentPanel.

      using Microsoft.Maui;
using Microsoft.Maui.Handlers;
...
public class MyContentViewHandler : ContentViewHandler
{
    public static IPropertyMapper<IContentView, IContentViewHandler> Mapper =
        new PropertyMapper<IContentView, IContentViewHandler>(ViewMapper)
        {
            [nameof(IContentView.Content)] = MapContent,
        };
            
    public static void MapContent(IContentViewHandler handler, IContentView page)
    {
        UpdateContent(handler);
    }

    static void UpdateContent(IContentViewHandler handler)
    {
        _ = handler.PlatformView ?? throw new InvalidOperationException($"{nameof(PlatformView)} should have been set by base class.");
        _ = handler.VirtualView ?? throw new InvalidOperationException($"{nameof(VirtualView)} should have been set by base class.");
        _ = handler.MauiContext ?? throw new InvalidOperationException($"{nameof(MauiContext)} should have been set by base class.");

        handler.PlatformView.Children.Clear();

        if (handler.VirtualView.PresentedContent is IView view)
        {
            // platform equivalent to Content.
            var platformContent = view.ToPlatform(handler.MauiContext);
    #if WINDOWS
            // Wrap content in a NavigationView.
            var navView = new NavigationView();
            navView.Content = platformContent;
            handler.PlatformView.Children.Add(navView);
    #else
            handler.PlatformView.Children.Add(platformContent);
    #endif
        }
    }
}

АЛЬТЕРНАТИВА 2 — Mapper.AppendToMapping

НЕПОЛНО... не знаю, как/где это сделать...

Техника: ПОСЛЕ выполнения стандартного сопоставления «исправьте» MyContentView.

      using Microsoft.UI.Xaml.Controls;

Microsoft.Maui.Handlers.ContentViewHandler.Mapper.AppendToMapping(
    "MyContentViewAsNavView", (handler, view) =>
    {
        if (view is MyContentView)
        {
    #if WINDOWS
            if (handler.PlatformView.Children.Count > 0) {
                // ASSUME first child is the Content to wrap.
                var platformContent = handler.PlatformView.Children[0];
                // Wrap content in a NavigationView.
                var navView = new NavigationView();
                navView.Content = platformContent;
                handler.PlatformView.Children[0] = navView;
            }
    #endif
        }
    });

ВАРИАНТ 3 - Адаптер "NavigationPanel"

(Вместо «вложения» NavigationView внутрь ContentPanel.)

  • Скопируйте исходники Maui ContentViewHandler.cs и ContentViewHandler.Windows.cs в файлы MyContent....
  • Замените «ContentView» на «MyContentView» и «ContentPanel» на «NavigationView».
  • Обратите внимание, что он не будет компилироваться. «CrossPlatformMeasure» и «CrossPlatformArrange» не существуют в «NavigationView».
  • Создайте новый класс «NavigationPanel», чтобы адаптировать «NavigationView». Эквивалент «ContentPanel», который адаптирует «Panel» для ContentView. Адаптировать из Microsoft.Maui.Platform.ContentPanelисточник.
  • Там, где вы ранее заменили «ContentPanel» на «NavigationView», вместо этого используйте этот новый «NavigationPanel».
Другие вопросы по тегам