英文:
Custom Control Library and specifying handlers
问题
我有一个自定义的MAUI控件库,我在多个项目中使用它。我已经将它转化为NuGet库,以便更容易重用。
在这个库中,有一个自定义的ContentPage(称之为ModalPage
),它有一个相应的自定义处理程序(称之为ModalPageHandler
),该处理程序派生自PageHandler,在iOS/MacCatalyst上执行一些魔法操作。在我的应用程序中,我使用标准的构建器调用在MauiProgram.cs中注册它:
builder.ConfigureMauiHandlers(handlers => {
handlers.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
});
一切都按预期工作。
然而,在控件库的上下文中,主应用程序中没有访问MauiAppBuilder的权限,因为它已经构建完成。
我如何配置我的控件库,使ModalPageHandler成为默认的处理程序,而无需消费者注册它?这肯定是可能的,因为MAUI控件也这样做...我只是找不到有关这种关联的文档。
英文:
I have a custom MAUI control library that I use across several projects. I've been turning it into a NuGet library to make reuse easier.
Within this library is a custom ContentPage (call it ModalPage
) that has an accompanying custom handler (call it ModalPageHandler
) that derives from PageHandler and performs some magic on iOS/MacCatalyst. In my apps, I register this using the standard builder call to ConfigureMauiHandlers in MauiProgram.cs:
builder.ConfigureMauiHandlers(handlers => {
handlers.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
});
Everything works as expected.
However within the context of a control library, there is no access to the MauiAppBuilder in the main app as it's already been built.
How do I configure my control library so that the ModalPageHandler is the default handler being used without the consumer registering it? It must be possible as MAUI controls do it...I just can't find documentation on that linkage.
答案1
得分: 1
目前,必须采用一种解决方法
在库中添加一个Init(builder)
函数,必须从MauiProgram.CreateMauiApp()
中调用,在每个使用您的库的应用程序中:
public static MauiApp CreateMauiApp()
{
var builder = ...;
...
MyLib.Init(builder); // 每个应用程序都必须执行此操作,否则您的处理程序/依赖注入服务将无法正常工作。
...
builder.Build();
}
在库中:
public static void Init(MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(handlers => {
handlers.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
});
builder.Services.AddSingleton<MyCustomComponent>();
}
这比必须明确引用处理程序本身要不那么显眼。
奖励 - (失败的) 尝试 - 几乎可以,只需要一个缺失的方法
尝试在页面类的静态构造函数中添加处理程序。
在库中:
public partial class MyPage : ContentPage
{
// 一次性初始化。
public static MyPage()
{
IMauiHandlersFactory handlersFactory = Application.Current.Handler?.MauiContext?.Handlers;
if (handlersFactory != null) {
// 编译错误:没有这样的方法。
// TODO: 没有方法可用于添加处理程序。它们只能由MauiAppBuilder添加。
handlersFactory.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
}
}
}
不幸的是,MauiAppBuilder.Build()运行后可用的接口只有getter;我看不到任何添加另一个处理程序的方法。
TODO:我没有调查,以找出运行时对象(handlersFactory的)是否是具有此方法的类。如果是这样,(不能保证在未来工作的)解决方法是将工厂转换为该类。然后建议将该方法提供给接口。
英文:
Currently, Must do a work-around
Add to library an Init(builder)
function that must be called from MauiProgram.CreateMauiApp()
in every app that uses your library:
public static MauiApp CreateMauiApp()
{
var builder = ...;
...
MyLib.Init(builder); // Every app must do this, or your handlers/DI-injected-services won't work correctly.
...
builder.Build();
}
In the library:
public static void Init(MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(handlers => {
handlers.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
});
builder.Services.AddSingleton<MyCustomComponent>();
}
That's less obtrusive than having to explicitly refer to the handlers themselves.
BONUS - (failed) ATTEMPT - ALMOST POSSIBLE, JUST NEED ONE MISSING METHOD
Attempt to add handler in page class static constructor.
In the library:
public partial class MyPage : ContentPage
{
// ONE-TIME initialization.
public static MyPage()
{
IMauiHandlersFactory handlersFactory = Application.Current.Handler?.MauiContext?.Handlers;
if (handlersFactory != null) {
// Compile error: No such method.
// TODO: No method exists to add handlers. They can only be added by MauiAppBuilder.
handlersFactory.AddHandler(typeof(ModalPage), typeof(ModalPageHandler));
}
}
}
Unfortunately, the Interfaces available after MauiAppBuilder.Build() runs, only have getters; I don't see any way to add another handler.
TODO: I didn't investigate, to find out whether the runtime object (of handlersFactory) is a class that has such a method. If so, a (not guaranteed to work in future) work-around is to cast factory to that class. Then propose that the method be made available on the interface.
答案2
得分: -2
首先,您可以在添加库的引用之后直接添加处理程序。例如:
.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
handlers.AddHandler(typeof(MauiLib1.NewPage1), typeof(MauiLib1.Platforms.Android.MyHandler));
#endif
});
我的项目结构如下:
此外,您还可以使用ContentPage的OnHandlerChanged方法来自定义内容页,而不是使用自定义处理程序。
英文:
First of all, you can add the handler directly after you added the reference of the library. Such as:
.ConfigureMauiHandlers(handlers =>
{
#if ANDROID
handlers.AddHandler(typeof(MauiLib1.NewPage1), typeof(MauiLib1.Platforms.Android.MyHandler));
#endif
});
And my project structure:
In addition, you can also use the ContentPage's OnHandlerChanged method to custom the content page instead of using the custom handler.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论