0

我开始将 MVVMLight 与 Xamarin.Forms 一起使用,并且需要一些帮助来设置 IOC 以在 App.GetMainPage 中创建我的第一个 ContentPage。

我的 ViewModel 有这样的构造函数——

public class NewsType1ViewModel : ViewModelBase
{
    private readonly IContentService contentService;
    private readonly INavigation navigation;

    public List<ContentModel> ContentModels { get; set; }

    public NewsType1ViewModel (INavigation navigation, IContentService contentService)
    {
        this.contentService = contentService;
        this.navigation = navigation;
    }

我的 ContentPages 有这样的构造函数 -

public partial class NewsType1CP : ContentPage
{
    private NewsType1ViewModel vm;

    public NewsType1CP (NewsType1ViewModel vm)
    {
        InitializeComponent ();

我正在使用 ViewModelLocator 类,如下所示 -

public class ViewModelLocator
{
    public ViewModelLocator ()
    {
        ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);

        // Services 
        if (App.StubMode) {
            SimpleIoc.Default.Register<IContentService, ContentServiceStub> ();
        } else {
            SimpleIoc.Default.Register<IContentService, ContentService> ();
        }

        // How do I wire up INavigation?
        // I could not just register default NavigationPage() as it has 2 
        // possible constructors so tried [PreferredConstructor] on my derived class
        SimpleIoc.Default.Register<INavigation, AppNavigationPage> ();

        // View Models
        SimpleIoc.Default.Register<NewsType1ViewModel> ();
        SimpleIoc.Default.Register<NewsDetailsViewModel> ();
    }

    public NewsType1ViewModel NewsType1ViewModel {
        get {
            return ServiceLocator.Current.GetInstance<NewsType1ViewModel> ();
        }
    }

    public NewsDetailsViewModel NewsDetailsViewModel {
        get {
            return ServiceLocator.Current.GetInstance<NewsDetailsViewModel> ();
        }
    }

    public static void Cleanup ()
    {
        // TODO Clear the ViewModels
    }
}

public class AppNavigationPage : NavigationPage
{
    [PreferredConstructor]
    public AppNavigationPage ()
    {

    }
}

我的 App.cs 正在“进行中”,如下所示 -

public static class App
{
    public static AppNavigationPage Nav;
    public static ViewModelLocator Locator = new ViewModelLocator ();

    public static bool StubMode = true;

    public static Page GetMainPage ()
    {   
        try {
            // Want to return a Nav with NewsType1CP as the starting Page
            NewsType1CP newsType1CP = new NewsType1CP(ServiceLocator.Current.GetInstance<NewsType1ViewModel> ());
            Nav.PushAsync (newsType1CP);
            return Nav;
        } catch (Exception ex) {
            //
            Exception baseexception = ex.GetBaseException ();
            Debug.WriteLine (baseexception.Message);
        }

        return null;
    }
}

我最近的例外是 -

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

我是否像这样试图为我的每个 ViewModel 提供 INavigation 错误的树?

更新:在几个答案显示了在 Xamarin Forms 中控制导航的其他方法之后,我认为如果有人能够澄清为什么尝试为导航注入构造函数不是一件好事,这将有所帮助。

我认为我的示例与作为静态的 AppNavigationPage 有点混淆,理想情况下我希望它也在 IOC 中,所以我可以调用 return ServiceLocator.Current.GetInstance< AppNavigationPage >(),但我尝试了各种工厂方法,并且正在调试它,所以代码显然是半生不熟的......

4

3 回答 3

2

如果您想要一个现成的解决方案,而不是 MVVM Light,您可以尝试使用Xamarin Forms Labs ViewModel 基础,它会在您的 ViewModel 中注入一个 Navigation 属性:

这样你冷做这样的事情:

 public Command NavigateToViewModel 
{
    get
    {
        return navigateToViewModel ?? (navigateToViewModel = new Command(
                                                                   async () => await Navigation.PushAsync<NewPageViewModel>(),
                                                                   () => true));
    }
}
于 2014-07-28T13:39:45.967 回答
1

我没有使用 MvvmLight,但我可以告诉你,是的,你在尝试为每个 ViewModel 提供 INavigation 时会出现错误的树。

实现您想要做的最简单的方法是在您的应用程序上使用公共静态。

public static INavigation Navigation
{
    get;
    set;
}
public static Page GetMainPage()
{
    var firstPage = new NavigationPage(new MyRootPage())
    {
        Navigation = firstPage.Navigation;
        return firstPage;
    }
}

现在,当您使用 MasterDetail 页面时,这会分崩离析,因为您需要 Navigation 来包装 DetailPage,而不是 MasterDetailPage。因此,不要Navigation在 GetMainPage 方法中设置,而是在 MD Page 中设置。

        var master = new MainMenuPage();
        var detail = new NavigationPage(new FirstPage());

        if (App.Navigation == null)
        {
            App.Navigation = detail.Navigation;
        }

        Master = master;
        Detail = detail;
于 2014-07-27T19:49:28.917 回答
0

哦,好的,当我更好地查看您的代码时,我可能发现了问题:

SimpleIoc.Default.Register<INavigation, AppNavigationPage> ();

应该是:

SimpleIoc.Default.Register<INavigation, AppNavigationPage.Navigation> ();
于 2014-07-28T15:30:35.313 回答