由于重写OnStartup,ResourceDictionary无法加载

时间:2015-11-03 14:56:04

标签: c# wpf xaml mvvm override

我正在使用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;
        }
    }
  }
}

3 个答案:

答案 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应用程序启动机制的更多详细信息,以便清除它。