[英]Caliburn Micro: how to navigate in Windows phone silverlight
i am trying to use Caliburn Micro in my windows phone 7 project.我正在尝试在我的 windows 手机 7 项目中使用 Caliburn Micro。 But i got a nullreferenceexception when navigate the page.
但是在导航页面时我得到了一个 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;
}
}
}
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);
}
}
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.如您所知,Caliburn.Micro 使用约定优于配置来定位 ViewModel 的视图,反之亦然,这意味着我们需要遵循约定。 My mistake was to have the
namespace
's inconsistent for the View and ViewModel我的错误是 View 和 ViewModel 的
namespace
不一致
In my case, I had就我而言,我有
MyWP7App.DetailsViewModel
, and MyWP7App.DetailsViewModel
和
MyWP7App.Views.DetailsView
--> I renamed the VM's namespace to be MyWP7App.ViewModels.DetailsViewModel
, and it worked out fine. --> 我将 VM 的命名空间重命名为
MyWP7App.ViewModels.DetailsViewModel
,结果很好。 I think I could have moved the view into MyWP7App.DetailsView
for a good result, too...我想我也可以将视图移到
MyWP7App.DetailsView
以获得良好的结果......
the call to Navigate()
invokes DeterminePageName()
which, in turn, invokes ViewLocator.LocateTypeForModelType
对
Navigate()
的调用会调用 DeletePageName DeterminePageName()
,后者又会调用ViewLocator.LocateTypeForModelType
This, like the rest of CM is overridable, but the default implementation looks like this:这个和CM的rest一样是可以覆盖的,但是默认实现是这样的:
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;
};
If you follow the debugger through, you end up with a collection viewTypeList
that contains MyWP7App.DetailsView
, and a type whose full name is MyWP7App.Views.DetailsView
, and the viewType
returned is therefore null... this is the cause of the NullReferenceException.如果您按照调试器进行操作,您最终会得到一个集合
viewTypeList
,其中包含MyWP7App.DetailsView
和一个全名为MyWP7App.Views.DetailsView
的类型,因此返回的viewType
是 null ......这是 NullReferenceException 的原因.
I'm 99% sure the NameTransformer.Transform
call will perform a pattern-match and transform the ViewModels
in the namespace of the VM to Views
in the namespace of the View it's trying to locate...我 99% 确定
NameTransformer.Transform
调用将执行模式匹配并将 VM 命名空间中的ViewModels
转换为它试图定位的 View 命名空间中的Views
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.