ResourceDictionary无法加载,因为覆盖OnStartup

问题描述:

我在做使用MVVM的wpf项目。 我在App.xaml.cs文件中使用override OnStartup,因为我使用NavigationService clas以在页面之间导航。 问题是在App.xaml文件中找到的ResourceDictionary未加载,因此我无法使用Locator。这里是我的代码 -ResourceDictionary无法加载,因为覆盖OnStartup

App.xaml文件:

<Application x:Class="TalkBackClient2.App" 

     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"> 
<Application.Resources> 

<ResourceDictionary> 

     <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:TalkBackClient2.ViewModel" /> 
    </ResourceDictionary> 

App.xaml.cs文件:

public partial class App : Application 
{ 
    Navigation.NavigationService nav; 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 
nav = new Navigation.NavigationService(); 
    } 
} 

的NavigationService文件:

namespace TalkBackClient2.Navigation 
{ 
class NavigationService 
{ 
    #region fields 
    private const WindowsEnum FirstScreen = WindowsEnum.LoginScreen; 
    private MainWindow mainWindow = new MainWindow(); 
    private LoginScreen loginScreen = new LoginScreen(); 
    private RegistrationScreen registrationScreen = new RegistrationScreen(); 
    private ChatScreen chatViewModel = new ChatScreen(); 
    private GameScreen gameScreen = new GameScreen(); 

    #endregion 

    public NavigationService() 
    { 
     Messenger.Default.Register<NavMessage>(this, navToPage); 
     openWindow(FirstScreen); 
    } 

    private void navToPage(NavMessage navMessage) 
    { 
     if (navMessage.NavFrom != WindowsEnum.MainWindow) 
     { 
      CloseWindow(navMessage.NavFrom); 
     } 

     openWindow(navMessage.NavToPage); 
    } 

    private void CloseWindow(WindowsEnum navFrom) 
    { 
     switch (navFrom) 
     { 
      case WindowsEnum.LoginScreen: 
       loginScreen.Hide(); 
       break; 
      case WindowsEnum.GameScreen: 
       gameScreen.Hide(); 
       break; 
      case WindowsEnum.RegistrationScreen: 
       registrationScreen.Hide(); 
       break; 
      case WindowsEnum.ChatScreen: 
       chatViewModel.Hide(); 
       break; 
      case WindowsEnum.MainWindow: 
       mainWindow.Hide(); 
       break; 
      default: 
       break; 
     } 
    } 

    private void openWindow(WindowsEnum navTo) 
    { 
     switch (navTo) 
     { 

      case WindowsEnum.RegistrationScreen: 
       if (registrationScreen == null) 
       { 
        registrationScreen = new RegistrationScreen(); 
       } 
       registrationScreen.Show(); 
       break; 
      case WindowsEnum.GameScreen: 
       if (gameScreen == null) 
       { 
        gameScreen = new GameScreen(); 
       } 
       gameScreen.Show(); 
       break; 

      case WindowsEnum.ChatScreen: 
       if (chatViewModel == null) 
       { 
        chatViewModel = new ChatScreen(); 
       } 
       chatViewModel.Show(); 
       break; 
      case WindowsEnum.MainWindow: 
        mainWindow = new MainWindow(); 
       var dataContext = (MainWindowViewModel)mainWindow.DataContext; 
       dataContext.Greeting = $"Greeting   {Util.LoggedInUser.UserName}"; 
        mainWindow.Show(); 
       break; 
      case WindowsEnum.LoginScreen: 
      default: 
       if (loginScreen == null) 
       { 
        loginScreen = new LoginScreen(); 
       } 
       loginScreen.Show(); 
       break; 
     } 
    } 
    } 
} 

HAV e您试图在app标签中定义名称空间xmlns:vm而不是在viewModel标签中?

+0

你的意思是写? 如果是这样,就没有应用程序标签,因为我可以看到.. –

+0

nop i meean''然后在您使用标签的资源中'' –

+0

我尝试了你的建议,但我得到一个运行时错误 - “找不到名为'locator'的资源。资源名称是区分大小写的。“虽然它显然有resourse(intellisense认出它) 我认为,确认它覆盖OnStartup碰巧之前资源被加载 –

我只是对同样的问题感到困惑。在玩了一段时间后(使用.NET 4.5.2),似乎有两种可能的解决方案(还有更多的困惑,因为我还没有找到背景为什么他们会工作)。

第一个解决方案:处理启动事件,而不是覆盖OnStartup。 显然,在事件处理程序中打开窗口时,ResourceDictionary会在窗口之前加载并可用。

解决方法二(我一个解释真的很好奇):把你的资源,资源字典是你的应用程序资源的合并资源字典里面。在这种情况下,即使覆盖OnStartup,合并的ResourceDictionary中的资源也可用于您的窗口。

<Application.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary> 
       [... your resource here ...] 
      </ResourceDictionary> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</Application.Resources> 

也许任何人都可以提供关于WPF应用程序启动机制的更多细节,可以清除它。