【问题标题】:Using Navigation in MasterDetailPage with Autofac and Xamarin.Forms使用 Autofac 和 Xamarin.Forms 在 MasterDetailPage 中使用导航
【发布时间】:2015-10-19 18:12:36
【问题描述】:

我正在尝试在 Xamarin.Forms 项目中使用 Autofac。我成功创建了基本示例,甚至将 ViewFactory 用于一些更复杂的示例。

但是,我无法将MasterDetailPage 与导航一起使用

我正在使用Jonathan Yates 编写的工厂和服务。你可以找到他的代码here

我的应用程序引导程序:

protected override void ConfigureApplication(IContainer container)
{
    var viewFactory = container.Resolve<IViewFactory>();
    var mainPage = viewFactory.Resolve<TestViewModel1>();

    var navigationPage = new NavigationPage(mainPage);
    var masterPage = new ContentPage();
    masterPage.Title = "asd";
    _application.MainPage = new MasterDetailPage()
    {
        Master = masterPage,
        Detail = navigationPage

    };
}

我的TestViewModel1 有一个导航到TestViewModel2 的命令:

ButtonCommand = new Command(async()=&gt;await _navigator.PushAsync&lt;TestViewModel2&gt;());

但是,应用程序因异常提示而崩溃

无法从源类型转换为目标类型。

Navigator 推送下一页时会发生这种情况。

堆栈跟踪:

" 在 TestIoc.TestModule+c.b__0_0 () [0x00000] 在 C:\Users\dushyantb\Documents\Visual Studio 2015\Projects\TestIoc\TestIoc\TestIoc\TestModule.cs:27 \n 在 TestIoc。 Views.PageProxy.get_Navigation () [0x00001] 在 C:\Users\dushyantb\Documents\Visual Studio 2015\Projects\TestIoc\TestIoc\TestIoc\Views\PageProxy.cs:39 \n 在 TestIoc.Navigator.get_Navigation () [ 0x00001] 在 C:\Users\dushyantb\Documents\Visual Studio 2015\Projects\TestIoc\TestIoc\TestIoc\Services\Navigator.cs:26 \n 在 TestIoc.Navigator+d__8`1[TestIoc.ViewModels.TestViewModel2].MoveNext () [0x0003a] 在 C:\Users\dushyantb\Documents\Visual Studio 2015\Projects\TestIoc\TestIoc\TestIoc\Services\Navigator.cs:58 "

我做错了什么?

注意:导航在没有 MasterDetailPage 时有效。

【问题讨论】:

  • 你能分享一下异常的堆栈跟踪吗?
  • 我已经用堆栈跟踪更新了这个问题。请检查一下...

标签: c# xamarin.ios autofac xamarin.forms


【解决方案1】:

确保不要覆盖 PageResolver,例如。不要接受 Jonathan 在他的 WeatherApp 示例中使用的覆盖:

builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);

核心组件中 PageResolver Func 的默认实现负责处理 MasterDetail 场景。请参阅 AutoFacModule.cs:

            // default page resolver
            builder.RegisterInstance<Func<Page>>(() =>
            {
                // Check if we are using MasterDetailPage
                var masterDetailPage = Application.Current.MainPage as MasterDetailPage;

                var page = masterDetailPage != null 
                    ? masterDetailPage.Detail 
                    : Application.Current.MainPage;

                // Check if page is a NavigationPage
                var navigationPage = page as IPageContainer<Page>;

                return navigationPage != null 
                    ? navigationPage.CurrentPage
                        : page;
            }
        );

我已经使用 Jonathan 的框架成功地使用 NavigationPage DetailViews 测试了 MasterDetail 场景。所以它应该可以工作。

在我的例子中,引导代码是

        protected override void ConfigureApplication(IContainer container)
        {

            // set main page
            var viewFactory = container.Resolve<IViewFactory>();

            var mainPage = viewFactory.Resolve<MainPageViewModel> ();
            _application.MainPage = mainPage;

        }

这意味着,我有一个 MainPageView,它是一个 MasterDetailPage,负责设置它的子视图:

    public class MainPage : MasterDetailPage
    {
        public MainPage (IViewFactory viewfactory)
        {
            Master = viewfactory.Resolve<MenuPageViewModel>();

            Detail = new NavigationPage (viewfactory.Resolve<DetailViewModel1>());

        }
    }

MenuPageViewModel 也使用 IViewFactory 来切换 MasterPages 的 Detail:

public class MenuPageViewModel : ViewModelBase
{
    IViewFactory _viewFactory;
    public MenuPageViewModel (IViewFactory viewFactory)
    {
        _viewFactory = viewFactory;

        ShowDetail1Command = new Command (ShowDetail1);
        ShowDetail2Command = new Command (ShowDetail2);
    }


    public ICommand ShowDetail1Command { get; set;}
    public void ShowDetail1() {
        var mainPage = _viewFactory.Resolve<MainPageViewModel> ();

        ((MasterDetailPage)mainPage).Detail = new NavigationPage (_viewFactory.Resolve<DetailViewModel1> ());
    }

    public ICommand ShowDetail2Command { get; set;}
    public void ShowDetail2() {
        var mainPage = _viewFactory.Resolve<MainPageViewModel> ();

        ((MasterDetailPage)mainPage).Detail = new NavigationPage (_viewFactory.Resolve<DetailViewModel2> ());
    }

}

希望这会有所帮助。

【讨论】:

  • 谢谢!我已经在 AutofacModule 中使用了处理 MasterDetail 场景的部分,但我也在我自己的模块中使用了 builder.RegisterInstance&lt;Func&lt;Page&gt;&gt;(() =&gt; ((NavigationPage)Application.Current.MainPage).CurrentPage);,该模块在 AutofacModule 之后注册。因此,以前的注册从未执行,我不知道为什么!只需要删除那一条语句。
  • 我不是专家,但我发现你的导航很奇怪。我可能是错的,但看起来您正在为Detail 设置一个新页面,而不是导航。
  • 没错,这只是一个快速破解。但是,尽管如此,您可以使用 AutoFac 将 DetailView 注册为 .SingleInstance() 并且您将始终获得相同的 DetailPage 实例。
  • @DushyantBangal 你能分享你的 module.cs 和 bootstrapper.cs,因为我遇到了 ViewModel 未注册之类的错误。谢谢
  • @jaketalledo,这是我的整个项目1drv.ms/u/s!AoFfM-gWzz5pgUnkdTA-JTsi15F8
猜你喜欢
  • 2014-10-12
  • 2018-07-01
  • 2017-09-01
  • 1970-01-01
  • 2019-04-08
  • 2014-12-28
  • 2017-01-24
  • 2018-12-10
  • 1970-01-01
相关资源
最近更新 更多