ResourceDictionary没有';由于重写OnStartup,无法加载
本文关键字:OnStartup 重写 加载 没有 于重写 ResourceDictionary | 更新日期: 2023-09-27 18:20:19
我正在使用MVVM进行wpf项目。我在App.xaml.cs文件中使用override OnStartup,因为我使用NavigationService类在页面之间导航。问题是在App.xaml文件中找到的ResourceDictionary没有加载,因此我无法使用Locator。这是我的代码-
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();
}
}
导航服务文件:
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;
}
}
}
}
正如fdub的答案中所建议的那样,在App.xaml
中使用合并字典。这里重要的是,只能链接到具有Source
属性的单独资源.xaml
文件。内联资源定义在这里是不可能的。
参见ResourceDictionary.MergedDictionaries
文档
示例:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
您是否尝试在app标签中而不是在viewModel标签中定义命名空间xmlns:vm?
我只是被同样的问题弄糊涂了。在玩了一点之后(使用.NET 4.5.2),似乎有两种可能的解决方案(这些方案让我更加困惑,因为我还没有找到它们为什么有效的背景)。
第一个解决方案:处理Startup事件,而不是覆盖OnStartup。显然,在事件处理程序中打开窗口时,ResourceDictionary会在之前加载,并且可用于您的窗口。
第二个解决方案(我真的很想得到解释):将您的资源放入ResourceDictionary中,该字典是应用程序资源的合并资源字典。在这种情况下,即使覆盖OnStartup,合并的ResourceDictionary中的资源也可用于您的窗口。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
[... your resource here ...]
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
也许任何人都可以提供更多关于WPF应用程序启动机制的细节,以澄清这一点。