Обработчики настраиваемых элементов управления .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».