Caliburn Micro:如何在 Windows Phone silverlight 中导航
我正在尝试在我的 Windows Phone 7 项目中使用 Caliburn Micro。 但我在导航页面时遇到了 nullreferenceException。
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);
}
}
i am trying to use Caliburn Micro in my windows phone 7 project.
But i got a nullreferenceexception when navigate the page.
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;
}
}
}
can anyone tell me what's the problem of my code? thanks in advance.
here is bootstrapper:
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我也遇到了这个问题,并进行了如下跟踪:
如您所知,Caliburn.Micro 使用约定优于配置来定位 ViewModel 的视图,反之亦然,这意味着我们需要遵循约定。我的错误是 View 和 ViewModel 的
namespace
不一致。在我的例子中,我有
MyWP7App.DetailsViewModel
和MyWP7App.Views.DetailsView
代码>-->我将虚拟机的命名空间重命名为
MyWP7App.ViewModels.DetailsViewModel
,效果很好。我认为我也可以将视图移动到 MyWP7App.DetailsView 中以获得良好的结果...在幕后
调用
Navigate()
调用DeterminePageName()
,而后者又调用ViewLocator.LocateTypeForModelType
这与 CM 的其余部分一样是可重写的,但默认实现如下所示:
如果您遵循通过调试器,您最终会得到一个包含
MyWP7App.DetailsView
的集合viewTypeList
,以及一个全名为MyWP7App.Views.DetailsView
的类型,因此返回的 viewType 为 null...这就是 NullReferenceException 的原因。我 99% 确信
NameTransformer.Transform
调用将执行模式匹配,并将虚拟机命名空间中的ViewModels
转换为Views
在它试图定位的视图的命名空间中...I had this too, and tracked it down as follows:
As you know, Caliburn.Micro uses convention-over-configuration to locate Views for ViewModels, and vice-versa, which means we need to follow the conventions. My mistake was to have the
namespace
's inconsistent for the View and ViewModelIn my case, I had
MyWP7App.DetailsViewModel
, andMyWP7App.Views.DetailsView
--> I renamed the VM's namespace to be
MyWP7App.ViewModels.DetailsViewModel
, and it worked out fine. I think I could have moved the view intoMyWP7App.DetailsView
for a good result, too...Under the covers
the call to
Navigate()
invokesDeterminePageName()
which, in turn, invokesViewLocator.LocateTypeForModelType
This, like the rest of CM is overridable, but the default implementation looks like this:
If you follow the debugger through, you end up with a collection
viewTypeList
that containsMyWP7App.DetailsView
, and a type whose full name isMyWP7App.Views.DetailsView
, and theviewType
returned is therefore null... this is the cause of the NullReferenceException.I'm 99% sure the
NameTransformer.Transform
call will perform a pattern-match and transform theViewModels
in the namespace of the VM toViews
in the namespace of the View it's trying to locate...