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;
        }
    }
  }
}

ResourceDictionary没有';由于重写OnStartup,无法加载

正如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应用程序启动机制的细节,以澄清这一点。