无法将WPFToolkit嵌入我的可执行文件中?

时间:2014-07-22 21:38:46

标签: wpf dll wpftoolkit

我曾经发过一篇关于此事的帖子,并没有找到有效的解决方案。 没有人说这是不可能的,但是有些人认为这个错误来自于别的东西。 所以我创建了一个新的解决方案,简单,只需添加一个工具包控件,它通过XAML(命名空间导入)调用DLL - 我认为这是问题所在。

我添加了一些代码来加载我作为资源嵌入的DLL。

我的项目可以从这里下载:

https://onedrive.live.com/redir?resid=B293BA834310C42A%21108

对于那些没有时间的人,这是代码:

MainWindow.xaml:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" x:Class="WpfAppTest1.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

        <chartingToolkit:ScatterSeries HorizontalAlignment="Left" Margin="63,85,0,0" VerticalAlignment="Top"/>

    </Grid>
</Window>

MainWindow.xaml.cs

namespace WpfAppTest1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

和我的App.xaml.cs

namespace WpfAppTest1
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        }
        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            var execAssembly = Assembly.GetExecutingAssembly();
            string resourceName = execAssembly.FullName.Split(',').First() + ".Resources." + new AssemblyName(args.Name).Name + ".dll";
            Console.WriteLine(resourceName);
            using (var stream = execAssembly.GetManifestResourceStream(resourceName))
            {
                byte[] assemblyData = new byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        }

    }
}

2 DLL是: system.windows.controls.datavisualization.toolkit.dll WPFToolkit.dll

两者都作为资源添加,构建操作设置为嵌入式资源。

2个引用是本地复制到False。

查看EXE,两个文件都内置于其中。 我添加了一个控制台写线来打印出正在加载的DLL的路径......

但我仍然收到错误。如果我将copy local设置为true,则可以正常工作。

我真的被困在那里并且必须使用这个工具包,我需要DLL作为EXE的一部分。如果不可能,那么我想从你们之一的专业人士那里阅读:)

感谢 史蒂夫

编辑:没有解决方案来实现我的需求吗? :(

编辑:到目前为止我还没有找到解决方案:/

编辑:我想知道这是否可能。

1 个答案:

答案 0 :(得分:1)

经过相当多的努力,我似乎​​有了这个工作。

由于system.windows.controls.datavisualization.toolkit的资源都是小写的,请确保对它的所有XAML引用都是,例如:

xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=system.windows.controls.datavisualization.toolkit"

这可确保Assembly.GetManifestResourceStream能够在没有任何外壳问题的情况下找到资源。

然后将程序集解析方法更改为以下内容:

private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    var requestedAssemblyName = new AssemblyName(args.Name).Name;

    const string resourcesExtension = ".resources";
    if (requestedAssemblyName.EndsWith(resourcesExtension, StringComparison.Ordinal))
    {
        requestedAssemblyName = requestedAssemblyName.Remove(requestedAssemblyName.Length - resourcesExtension.Length);
    }

    var resourceName = "WpfAppTest1.Resources." + requestedAssemblyName + ".dll";
    var appAssembly = typeof(App).Assembly;
    using (var stream = appAssembly.GetManifestResourceStream(resourceName))
    {
        // Check the resource was found
        if (stream == null)
            return null;

        var assemblyData = new byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        var loadedAssembly = Assembly.Load(assemblyData);

        return loadedAssembly;
    }
}

要注意的关键点是删除.resources扩展名,有时在解析程序集时会出现

这足以从资源中获取程序集加载,但是没有应用于图表控件的隐式样式(我假设这与WPF在运行时发现其主题的方式有关)。

要解决此问题,我将以下内容放在App.xaml中:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/system.windows.controls.datavisualization.toolkit;component/Themes/generic.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

这会合并默认的图表样式,然后应该隐式应用它们。

为了测试它,我在MainWindow.xaml中使用了以下内容:

<chartingToolkit:Chart Title="Some Chart" Background="Blue">
    <chartingToolkit:Chart.Series>
        <chartingToolkit:ScatterSeries Title="Series 1" />
    </chartingToolkit:Chart.Series>
</chartingToolkit:Chart>