Caliburn Micro:如何在Windows Phone silverlight中导航

本文关键字:Phone silverlight 导航 Windows Micro Caliburn | 更新日期: 2023-09-27 17:59:03

我正在尝试在我的Windows Phone 7项目中使用Caliburn Micro。但是我在导航页面时遇到了一个空引用异常。

namespace Caliburn.Micro.HelloWP7 {
    public class MainPageViewModel {
        readonly INavigationService navigationService;
        public MainPageViewModel(INavigationService navigationService) {
            this.navigationService = navigationService;
        }
        public void GotoPageTwo() {
            /*navigationService.UriFor<PivotPageViewModel>()
                .WithParam(x => x.NumberOfTabs, 5)
                .Navigate();*/
            navigationService.UriFor<Page1ViewModel>().Navigate();
        }
    }
}
namespace Caliburn.Micro.HelloWP7
{
    public class Page1ViewModel
    {
         readonly INavigationService navigationService;
         public Page1ViewModel(INavigationService navigationService)
         {
            this.navigationService = navigationService;
        }
    }
}

谁能告诉我我的代码有什么问题?提前谢谢。

这是引导程序:

public class ScheduleBootstrapper : PhoneBootstrapper
{
    PhoneContainer container;
    protected override void Configure()
    {
        container = new PhoneContainer(RootFrame);
        container.RegisterPhoneServices();
        container.PerRequest<MainPageViewModel>();
        container.PerRequest<MainContentViewModel>();
        container.PerRequest<Page1ViewModel>();
        AddCustomConventions();
    }
    static void AddCustomConventions()
    {
        ConventionManager.AddElementConvention<Pivot>(Pivot.ItemsSourceProperty, "SelectedItem", "SelectionChanged").ApplyBinding =
            (viewModelType, path, property, element, convention) =>
            {
                if (ConventionManager
                    .GetElementConvention(typeof(ItemsControl))
                    .ApplyBinding(viewModelType, path, property, element, convention))
                {
                    ConventionManager
                        .ConfigureSelectedItem(element, Pivot.SelectedItemProperty, viewModelType, path);
                    ConventionManager
                        .ApplyHeaderTemplate(element, Pivot.HeaderTemplateProperty, viewModelType);
                    return true;
                }
                return false;
            };
        ConventionManager.AddElementConvention<Panorama>(Panorama.ItemsSourceProperty, "SelectedItem", "SelectionChanged").ApplyBinding =
            (viewModelType, path, property, element, convention) =>
            {
                if (ConventionManager
                    .GetElementConvention(typeof(ItemsControl))
                    .ApplyBinding(viewModelType, path, property, element, convention))
                {
                    ConventionManager
                        .ConfigureSelectedItem(element, Panorama.SelectedItemProperty, viewModelType, path);
                    ConventionManager
                        .ApplyHeaderTemplate(element, Panorama.HeaderTemplateProperty, viewModelType);
                    return true;
                }
                return false;
            };
    }
    protected override object GetInstance(Type service, string key)
    {
        return container.GetInstance(service, key);
    }
    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return container.GetAllInstances(service);
    }
    protected override void BuildUp(object instance)
    {
        container.BuildUp(instance);
    }
}

Caliburn Micro:如何在Windows Phone silverlight中导航

我也有这个,并按如下方式追踪它:

如您所知,Caliburn.Micro 使用约定重配置来定位 ViewModel 的视图,反之亦然,这意味着我们需要遵循约定。我的错误是视图和视图模型的namespace不一致

就我而言,我有

MyWP7App.DetailsViewModel

MyWP7App.Views.DetailsView

-

-> 我将 VM 的命名空间重命名为 MyWP7App.ViewModels.DetailsViewModel ,效果很好。我想我也可以将视图移到MyWP7App.DetailsView以获得好的结果......

<小时 />

在幕后

Navigate()的调用调用DeterminePageName()而反过来又调用ViewLocator.LocateTypeForModelType

与 CM 的其余部分一样,这是可覆盖的,但默认实现如下所示:

public static Func<Type, DependencyObject, object, Type> LocateTypeForModelType = (modelType, displayLocation, context) => {
    var viewTypeName = modelType.FullName.Substring(
        0,
        modelType.FullName.IndexOf("`") < 0
            ? modelType.FullName.Length
            : modelType.FullName.IndexOf("`")
        );
    Func<string, string> getReplaceString;
    if (context == null) {
        getReplaceString = r => { return r; };
    }
    else {
        getReplaceString = r => {
            return Regex.Replace(r, Regex.IsMatch(r, "Page$") ? "Page$" : "View$", ContextSeparator + context);
        };
    }
    var viewTypeList = NameTransformer.Transform(viewTypeName, getReplaceString);
    var viewType = (from assembly in AssemblySource.Instance
                    from type in assembly.GetExportedTypes()
                    where viewTypeList.Contains(type.FullName)
                    select type).FirstOrDefault();
    return viewType;
};

如果你按照调试器进行操作,你最终会得到一个包含 MyWP7App.DetailsView 的集合viewTypeList,以及一个全名为 MyWP7App.Views.DetailsView 的类型,因此返回的viewType为 null...这是 NullReferenceException 的原因。

我 99% 确定 NameTransformer.Transform 调用将执行模式匹配并将 VM 命名空间中的ViewModels转换为Views它尝试定位的视图命名空间中的......