我正在使用MVVM做wpf项目。 我在App.xaml.cs文件中使用覆盖OnStartup,因为我使用NavigationService clas来在页面之间导航。 问题是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();
}
}
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;
}
}
}
}
答案 0 :(得分:1)
如 fdub's answer 中所提议,在 App.xaml
中使用合并字典。
这里重要的是,只能链接到具有 .xaml
属性的单独资源 Source
文件。内联资源定义在这里是不可能的。
请参阅 docs 以了解 ResourceDictionary.MergedDictionaries
示例:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
答案 1 :(得分:0)
您是否尝试在app标记中而不是在viewModel标记中定义命名空间xmlns:vm?
答案 2 :(得分:0)
我对同样的问题感到困惑。在玩了一下之后(使用.NET 4.5.2),似乎有两种可能的解决方案(这些解决方案更让我困惑,因为我还没有找到他们工作原理的背景。)
第一个解决方案:处理启动事件而不是覆盖OnStartup。 显然,当在事件处理程序中打开一个窗口时,ResourceDictionary会在之前加载并可用于您的窗口。
第二个解决方案(我对解释非常好奇):将您的资源放在ResourceDictionary中,这是您的App资源的合并ResourceDictionary。在这种情况下,即使重写OnStartup,合并的ResourceDictionary中的资源也可用于您的窗口。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
[... your resource here ...]
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
也许任何人都可以提供有关WPF应用程序启动机制的更多详细信息,以便清除它。