从 WPFapplication 创建的可运行 Dll 找不到引用的 ResourceDictionary

问题描述 投票:0回答:1

我现在搜索了一段时间,没有找到具体问题的解决方案。

首先,我开发了一个包含多个项目和用户控件的 WPF 应用程序,在多个项目中使用相同的 ResourceDictionary。因此,我在一个仅包含dictionary.xaml的项目中获取了资源字典:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WPFGlobalResources;assembly=WPFGlobalResources"
                    >

    <!--Here are placed some styles I use globally -->    
    
</ResourceDictionary>

在我的许多 Windows 和 UserControls 中,我在项目中引用了 WPFGlobalResources 并添加了

<Window.Resources> or UserControl.Resources
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/WPFGlobalResources;component/GlobalWpfResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

在 xaml 的开头。

只要我使用可执行应用程序,一切都会正常工作,并且可以加载所有资源。

现在我需要此应用程序的可运行 Dll 版本才能在 Windows 注册表中注册它。为此,我将 App.xaml 从我的项目中剔除,并将其转变为类库,正如我在许多 Google 网站中所描述的那样。

在那里注册,我可以从 CAD 程序中调用它 - 在此程序中,它使用调用

DLL MainApplication.exec 1
,它需要我的 DLL 项目中的以下方法来获取新的 EntryPoint(我为其使用了一个额外的类):

public class Exec
{
    public short vcExtStartUp(ref string Directory, string ExtensionName)
    {   //I don't use this method
        return 1;

    }

    public short vcExtMenuExec(ref int MenuID)
    {   //this is what I need to run a WPF Application
        Application app = new Application();

        app.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative); ;
        
        app.Run(new MainWindow());
        return 1;
    }
}

这里我只需要第二种方法,如你所见。我原来的项目在这里抛出了一些错误,所以我尽可能减少了我的问题,仅使用包含 WPFGlobalResources 的项目和一个包含几乎空的 MainWindow 的项目,其中包含一个按钮,使用字典中的样式以及对项目的引用我的字典。

只要我在 MainWindow.xaml 的开头注释掉 mergedDictionary 的调用,一切就可以正常工作(当然我当时没有按钮样式)。 如果我尝试使用 ResourceDictionary,我的 CAD 程序会在调用 DLL 时崩溃,并且调试器会导致我出现错误:(希望我正确翻译了它)

IOException - 附加信息:Assembly.GetEntryAssembly() 返回 NULL。定义 Application.ResourceAssembly-Property 或使用语法“pack://application:,,,/ assemblyname;component/”来定义应从中加载资源的程序集。

好的,然后我在 new Application() 后面添加了

Application.ResourceAssembly = typeof(MainWindow).Assembly;
。现在调试器向前移动了一点,但再次停止并出现错误:

MainWindow.xaml linenumer12 中的异常 ... -> InnerException {“文件或程序集“WPFGlobalResources,Culture=neutral”或其依赖项无法找到。系统找不到指定的文件。”:“WPFGlobalResources,Culture =中性”} System.Exception {System.IO.FileNotFoundException}

我也尝试过添加

System.Uri resourceLocater = new System.Uri("/MainApplication;component/VisiDockedMainWindow.xaml", System.UriKind.Relative);

System.Windows.Application.LoadComponent(resourceLocater);

但没有成功,仍然是同样的错误。

现在我找不到让它发挥作用的解决方案。是否有可能 pack://application... 现在将我的 CAD 程序作为应用程序而不是 WPFGlobalResources.dll(以及所有其他 dll)所在的 DLL 的位置?我该如何更改它,我在 MSDN 中找不到此用例的 URI。

接下来我要尝试的是转储我的 WPFGlobalResources 并将样式添加到每个窗口/用户控件,但我希望这不是唯一的解决方案???产生大量冗余代码...

c# wpf xaml dll resourcedictionary
1个回答
0
投票

好吧,经过多次尝试,我同时找到了解决方案:

问题是,在执行主窗口的 xaml 代码时,引用似乎没有被加载。解决方案很简单,添加一个:

Assembly resAssembly = Assembly.Load("WPFGlobalResources");

在使用app.Run之前。 这似乎预加载了外部参考,然后就可以找到它了。

有趣的提示:在这种情况下,最好不要对 WPF 应用程序进行任何更改(仍然可以使用 App.xaml 执行)并添加额外的 Classlibrary-Project 来创建 dll。然后你可以添加一个类来启动你的WPF应用程序(当然你必须首先引用WPF-Projekt和ResourceDictionary-Projekt):

public class Exec
{

    public short vcExtStartUp(ref string Directory, string ExtensionName)
    {
        return 1;

    }

    public short vcExtMenuExec(ref int MenuID)
    {
        Thread thread = new Thread(() =>
        {
            WpfTestAppl.App app = new WpfTestAppl.App();

            // Loading of ResourceAssemblys                
            Assembly resAssembly = Assembly.Load("WPFGlobalResources");


            app.Run(new WpfTestAppl.MainWindow());

        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

        return 1;
    }
}

现在终于可以工作了:-)

© www.soinside.com 2019 - 2024. All rights reserved.