2014-09-23 138 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. 

感謝亞歷山大,你的代碼對我來說是很好的起點。

相關問題