2014-09-23 76 views
0

我正在学习windows store应用程序中的棱镜。我遇到了问题。我有很多意见,我想将它们分成不同的文件夹。但问题在于NavigationService无法找到它们。说明书说,所有视图显示放入视图文件夹,然后导航服务可以使用navigationservice.navigate(“main”,null)导航到它们,但是如果视图不在导航服务找不到它们的视图文件夹的根目录棱镜如何找到视图文件夹的子文件夹中的视图

+0

欢迎来到StackOverflow!为了让人们更容易回答,您可能需要提供有关您遇到的问题的更多详细信息。代码或屏幕截图,以及对问题和已经尝试过的更详细的解释可以提供帮助。 – Denise 2014-09-23 02:46:55

回答

5

NavigationService根据约定查找Views和ViewModels。所有视图必须位于“视图”文件夹中,并且ViewModels必须位于“ViewModels”文件夹中。如果ID不适合你可以做到以下几点:

  1. 添加下面的类到你的项目:

    public class ViewViewModelTypeResolver 
    { 
        private const string ViewNameSuffix = "Page"; // You can change this View name suffix 
        private const string ViewModelNameSuffix = "ViewModel"; // You can change this ViewModel name suffix 
    
        private readonly Lazy<Dictionary<string, Type>> _uiAssemblyExportedTypes; 
    
        private Dictionary<string, Type> UiAssemblyExportedTypes 
        { 
         get { return _uiAssemblyExportedTypes.Value; } 
        } 
    
        public ViewViewModelTypeResolver(Type typeFromUiAssembly) 
        { 
         _uiAssemblyExportedTypes = new Lazy<Dictionary<string, Type>>(() => GetUiAssemblyExportedTypes(typeFromUiAssembly)); 
        } 
    
        public Type GetViewType(string viewTypeName) 
        { 
         return UiAssemblyExportedTypes[viewTypeName]; 
        } 
    
        public Type GetViewModelType(Type viewType) 
        { 
         var pageNameWithoutSuffix = viewType.Name.Remove(viewType.Name.LastIndexOf(ViewNameSuffix, StringComparison.Ordinal)); 
         var viewModelName = String.Concat(pageNameWithoutSuffix, ViewModelNameSuffix); 
         return UiAssemblyExportedTypes[viewModelName]; 
        } 
    
    
        private static Dictionary<string, Type> GetUiAssemblyExportedTypes(Type typeFromUiAssembly) 
        { 
         return typeFromUiAssembly.GetTypeInfo().Assembly.ExportedTypes.ToDictionary(type => type.Name, type => type, StringComparer.Ordinal); 
        } 
    } 
    
  2. 添加ViewViewModelTypeResolver到App构造函数:

    public App() 
    { 
        var mainPage = typeof(MainPage); // Any of pages from your solution. Pay attention that the resolver will be able to resolve Views and ViewModels that locates in the same project as specified page. 
        _viewViewModelTypeResolver = new ViewViewModelTypeResolver(mainPage); 
    } 
    
  3. 当你使用Prism时,我假设你从MvvmAppBase继承你的App类。如果是这样,你应该重写GetPageType方法:

    protected override Type GetPageType(string pageToken) 
        { 
         return _viewViewModelTypeResolver.GetViewType(pageToken); 
        } 
    
  4. 然后在OnInitializeAsync方法添加SetDefaultViewTypeToViewModelTypeResolver

    protected override async Task OnInitializeAsync(IActivatedEventArgs args) 
    { 
        // Your initialization code 
    
        ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(GetViewModelType); 
    
        // Your initialization code 
    } 
    
    private Type GetViewModelType(Type pageType) 
    { 
        return _viewViewModelTypeResolver.GetViewModelType(pageType); 
    } 
    

现在你可以浏览到任何网页上,即使它们被分成不同的文件夹。

0

来自Alexander.Ermolaev的很好回答。我想扩展他的课程以满足我的需求。我不喜欢公开所有的ViewModel。当我们真正需要的是Views和ViewModels的类型时,我也不想保留所有类型的字典。这将查找从UserControl继承的所有视图,因为ViewModelLocator将与UserControl以及Pages一起使用。这将找到所有从基本视图模型类继承的ViewModel,通常是Prism的ViewModelBase。从App.cs

sealed class ViewViewModelTypeResolver 
{ 
    private readonly Assembly _assembly; 
    private readonly Type _baseViewModelType; 
    private readonly string _viewNameSuffix; 
    private readonly string _viewModelNameSuffix; 
    private readonly Lazy<Dictionary<string, Type>> _views; 
    private readonly Lazy<Dictionary<string, Type>> _viewModels; 

    private Dictionary<string, Type> Views => _views.Value; 
    private Dictionary<string, Type> ViewModels => _viewModels.Value; 

    /// <summary> 
    /// Resolves Views and ViewModels. 
    /// </summary> 
    /// <param name="typeFromUiAssembly">Use any type from the UI Assembly.</param> 
    /// <param name="baseViewModelType">All view models need to inherit from this type.</param> 
    /// <param name="viewNameSuffix">Prism convention is to name your views with a Page suffix.</param> 
    /// <param name="viewModelNameSuffix">Prism convention is name your viewmodels with a ViewModel suffix.</param> 
    public ViewViewModelTypeResolver(Type typeFromUiAssembly, Type baseViewModelType, string viewNameSuffix = "Page", string viewModelNameSuffix = "ViewModel") 
    { 
     _baseViewModelType = baseViewModelType; 
     _viewNameSuffix = viewNameSuffix; 
     _viewModelNameSuffix = viewModelNameSuffix; 
     _assembly = typeFromUiAssembly.GetTypeInfo().Assembly; 

     _views = new Lazy<Dictionary<string, Type>>(GetViews); 
     _viewModels = new Lazy<Dictionary<string, Type>>(GetViewModels); 
    } 

    /// <summary> 
    /// Gets a View type for the given name. 
    /// </summary> 
    /// <param name="viewTypeName">Name of the view without the suffix.</param> 
    public Type GetViewType(string viewTypeName) 
    { 
     var pageName = string.Concat(viewTypeName, _viewNameSuffix); 
     return this.Views[pageName]; 
    } 

    /// <summary> 
    /// Gets a ViewModel for the given view type. 
    /// </summary> 
    /// <param name="viewType">Type of view.</param> 
    public Type GetViewModelType(Type viewType) 
    { 
     var viewModelName = string.Concat(viewType.Name, _viewModelNameSuffix); 
     return this.ViewModels[viewModelName]; 
    } 

    /// <summary> 
    /// Gets all the View types by finding all types that inherit from Page and are defined in the UI Assembly. 
    /// </summary> 
    private Dictionary<string, Type> GetViews() 
    { 
     var types = _assembly.DefinedTypes.Where(type => !type.IsAbstract && type.IsSubclassOf(typeof(UserControl))); 

     return types.ToDictionary(typeInfo => typeInfo.Name, typeInfo => typeInfo.AsType(), StringComparer.Ordinal); 
    } 

    /// <summary> 
    /// Gets all the ViewModel types by finding all types that inherit from a base ViewModel type defined in the UI Assembly. 
    /// </summary> 
    private Dictionary<string, Type> GetViewModels() 
    { 
     var types = _assembly.DefinedTypes.Where(type => !type.IsAbstract && type.IsSubclassOf(_baseViewModelType)); 

     return types.ToDictionary(typeInfo => typeInfo.Name, typeInfo => typeInfo.AsType(), StringComparer.Ordinal); 
    } 
} 

用法:

private readonly ViewViewModelTypeResolver _viewViewModelTypeResolver; 

public App() 
{ 
    this.InitializeComponent(); 

    _viewViewModelTypeResolver = new ViewViewModelTypeResolver(this.GetType(), typeof(ViewModelBase)); 
} 

//other methods are the same as Alexander's answer. 

感谢亚历山大,你的代码对我来说是很好的起点。

相关问题