提问人:Akshay Kumar 提问时间:7/17/2023 最后编辑:Akshay Kumar 更新时间:7/21/2023 访问量:333
MAUI 中的处理程序仅在示例项目中起作用。未调用处理程序类中的 Constructor 或 CreatePlatformView 或 ConnectHandler
Handlers in MAUI is working only in sample project. The Constructor or CreatePlatformView or ConnectHandler from handler class is not getting called
问:
使用 Xamarin Forms 创建了一个 iOS 应用(该应用仅适用于 iOS)。Xamarin 项目具有用于显示上下文菜单的 CustomRenderer。如下图所示
升级到 MAUI 后,我尝试重用相同的 CustomRenderer。 它未在 MAUI 项目中显示上下文菜单。使用 CustomRenderer 时,它甚至没有调用 OnElementChanged 方法。
我决定为此创建一个处理程序。它也不会显示上下文菜单。甚至处理程序类中的 Constructor 或 CreatePlatformView 或 ConnectHandler 也没有被调用。 我不确定出了什么问题。
处理程序代码如下所述。
在 MauiProgram 类中,我使用以下行注册了 Handler:
handlers.AddHandler(typeof(ContextMenuView), typeof(ContextMenuViewHandler));
自定义控件定义如下:
public class ContextMenuView : View
{
public MenuRequested MenuRequested;
public void RequestMenu(object sender, double x, double y, double width, double height)
{
MenuRequested?.Invoke(sender, new MenuRequestedEventArgs(x, y, width, height));
}
public bool CanCut { get; set; } = true;
public bool CanCopy { get; set; } = true;
public bool CanDelete { get; set; } = true;
public bool HasProperties { get; set; } = true;
public Action OnCopy { get; set; }
public Action OnDelete { get; set; }
public Action OnProperties { get; set; }
public Action OnCut { get; set; }
public IContextCommand[] Commands { get; set; }
}
处理程序定义如下:
public class ContextMenuViewHandler : ViewHandler<ContextMenuView, ContextMenuiOS>
{
private nfloat _height;
private nfloat _width;
string ACTION_PREFIX = "custom_action";
int MAX_CUSTOM_ACTIONS = 4;
public static IPropertyMapper<ContextMenuView, ContextMenuViewHandler> PropertyMapper =
new PropertyMapper<ContextMenuView, ContextMenuViewHandler>(ViewHandler.ViewMapper)
{
};
public ContextMenuViewHandler() : base(PropertyMapper)
{
}
protected override ContextMenuiOS CreatePlatformView()
{
return new ContextMenuiOS(VirtualView);
}
protected override void ConnectHandler(ContextMenuiOS platformView)
{
base.ConnectHandler(platformView);
VirtualView.MenuRequested += OnMenuRequested;
}
protected override void DisconnectHandler(ContextMenuiOS platformView)
{
base.DisconnectHandler(platformView);
VirtualView.MenuRequested -= OnMenuRequested;
}
private void OnMenuRequested(object _, MenuRequestedEventArgs e)
{
try
{
var _menu = UIMenuController.SharedMenuController;
PlatformView.BecomeFirstResponder();
var items = new List<UIMenuItem>();
if (VirtualView.Commands?.Any() == true)
{
var index = 0;
foreach (var item in VirtualView.Commands.Where(o => o.Command.CanExecute(null)).Take(MAX_CUSTOM_ACTIONS))
{
items.Add(new UIMenuItem
{
Title = item.Name,
Action = new Selector($"{ACTION_PREFIX}{index++}:")
});
}
}
if (VirtualView.HasProperties)
{
items.Add(new UIMenuItem("Options...", new Selector("Properties:")));
}
_menu.MenuItems = items.ToArray();
_menu.SetTargetRect(new CGRect(e.X, e.Y, e.Width, e.Height), PlatformView);
_menu.MenuVisible = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
ContextMenuiOS 定义如下:
public class ContextMenuiOS : UIView
{
private nfloat _height;
private nfloat _width;
const string ACTION_PREFIX = "custom_action";
const int MAX_CUSTOM_ACTIONS = 4;
ContextMenuView Mauiview;
public ContextMenuiOS(ContextMenuView view)
{
Mauiview = view;
_height = UIScreen.MainScreen.Bounds.Height;
_width = UIScreen.MainScreen.Bounds.Width;
Frame = new CGRect(0, 0, _width, _height);
}
public override bool CanBecomeFirstResponder => true;
public override bool CanPerform(Selector action, NSObject withSender)
{
switch (action.Name)
{
case "Properties:":
return Mauiview.HasProperties;
case "cut:":
return Mauiview.CanCut;
case "copy:":
return Mauiview.CanCopy;
case "delete:":
return Mauiview.CanDelete;
}
if (action.Name.StartsWith(ACTION_PREFIX))
{
var indexString = action.Name.Substring(ACTION_PREFIX.Length, action.Name.Length - ACTION_PREFIX.Length - 1);
var index = int.Parse(indexString);
return Mauiview.Commands[index].Command.CanExecute(null);
}
return true;
}
[Export("Properties:")]
public void Properties(UIMenuController controller)
{
Mauiview?.OnProperties();
}
[Export("custom_action0:")]
public void Action0(UIMenuController controller)
{
Mauiview.Commands[0].Command.Execute(null);
}
[Export("custom_action1:")]
public void Action1(UIMenuController controller)
{
Mauiview.Commands[1].Command.Execute(null);
}
[Export("custom_action2:")]
public void Action2(UIMenuController controller)
{
Mauiview.Commands[2].Command.Execute(null);
}
[Export("custom_action3:")]
public void Action3(UIMenuController controller)
{
Mauiview.Commands[3].Command.Execute(null);
}
public override void Cut(NSObject sender)
{
Mauiview?.OnCut();
}
public override void Copy(NSObject sender)
{
Mauiview?.OnCopy();
}
public override void Delete(NSObject sender)
{
Mauiview?.OnDelete();
}
}
注意:我尝试创建一个示例项目以在 GitHub 中发布。 但在示例项目中,相同的代码显示在上下文菜单中。
可以通过以下链接找到示例项目存储库:The sample project repo can be found with the following link: https://github.com/apy534/MAUI-Handler-test
默认情况下,gitHub 项目使用 CustomRenderer。您可以通过在 MauiProgram 类中将 Render 注册更改为 handler 来从 CustomRenderer 切换到 Handler。
有人面临类似的问题吗?
答: 暂无答案
评论