C# - 从不同程序集加载图像

9 浏览
0 Comments

C# - 从不同程序集加载图像

我有一张图片在不同的程序集中:

  • (.NET Standard 1.4) ResourcesAssembly/Common/Images/CompanyLogo.png - 强制要求
  • Build Action: Content - 强制要求
  • Copy to output directory: Copy if newer (我在编译后检查过 - 所需的图片存在于输出目录中,即我的exe所在的位置 - 例如,Debug/Common/Images/CompanyLogo.png。所以从那里获取应该没有问题。)

我想把它粘贴到我的应用程序的程序集(WPF)中的一个窗口里。我尝试了两种变体。

1.


界面中的图像在运行时可见。但是VS的XAML设计器在设计时不显示图像,并显示错误信息:

找不到路径的一部分 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Common\Images\CompanyLogo.png'。

2.


图像在运行时不可见,但在设计时一切正常。

Visual Studio 2017 Community Edition 15.4.4。

所以第一种变体对我来说似乎合适,但是那个奇怪的错误 - 为什么它尝试在Visual Studio文件夹中找到图像呢?"siteoforigin"选项与应用程序exe相关,而不是Visual Studio exe,对吗?

更新

尝试了第二种变体,以"嵌入资源"的构建操作(ResourcesAssembly是一个.NET Standard 1.4项目)。甚至清理并重新构建了解决方案。结果与第二种变体相同:图像在运行时不可见,但在设计时可见。

0
0 Comments

问题出现的原因是在WPF中加载不同程序集中的图像时,application在设计时正常工作,但在运行时不起作用,而siteoforigin则相反。

解决方法是在控件的Source属性设置时进行拦截。一种方法是使用继承。下面是一个针对ResourceDictionary的示例实现:

/// 
/// A modified type of  that translates "Resource" pack URIs to "Site of Origin"
/// pack URIs when in runtime.
///
/// i.e. This allows you to declare pack URIs as "pack://application:,,,", which will be resolved
/// as such in design mode while at runtime, actually using "pack://siteoforigin:,,,".
/// 
public class SiteOfOriginResourceDictionary : ResourceDictionary
{
    private const string SiteOfOriginPrefix = "pack://siteoforigin:,,,";
    private const string ApplicationPrefix = "pack://application:,,,";
    private const string UseRedirectSource = "Please use RedirectSource instead of Source";
    private string _originalUri;
    /// 
    /// Gets or sets the design time source.
    /// 
    public string RedirectSource
    {
        get => _originalUri;
        set
        {
            this._originalUri = value;
            bool isInDesignMode = (bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue;
            if (!isInDesignMode)
            {
                if (value.Contains(ApplicationPrefix))
                    value = value.Replace(ApplicationPrefix, SiteOfOriginPrefix);
            }
            base.Source = new Uri(value);
        }
    }
    /// 
    /// Please use  instead.
    /// 
    public new Uri Source
    {
        get => throw new Exception(UseRedirectSource);
        set => throw new Exception(UseRedirectSource);
    }
}

使用示例:


    
        
            
        
    

这种解决方法在实践中对我起到了作用,并且我经常使用这段代码。我相信你也可以在Image和其他WPF组件中使用相同的方法。

另外,我不知道为什么在将资源的构建操作设置为Content时,使用application在设计时起作用。根据文档,这个URI应该在资源"被编译到引用的程序集中"时使用,但是对我来说,这个方法可以正常工作。

这是我在StackOverflow上的第一篇帖子,我是一个业余爱好者,请多多指教 。

0
0 Comments

在使用Visual Studio的XAML设计器时,执行的程序集是XDesProc.exe(位于指定目录C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE)。这就是为什么图像搜索路径是...\IDE\Common\Images\CompanyLogo.png的原因。

如果你想同时满足两个要求(第一,图像在外部资源程序集中,第二,图像的构建操作设置为'Content'),那么可能没有办法同时在WPF设计器和应用程序运行时正确显示图像。至少我无法找到解决方案。

siteorigin权限在打包URI中不适用,因为图像应该在不同的应用程序中加载,这些应用程序具有不同的执行目录。

application权限在打包URI中不适用,因为它仅适用于编译到程序集中(本地或引用的)的资源文件。这实际上是为什么你在第二个变体中在运行时看不到图像的原因。

所以,如果第一个变体适合你,那么好吧,这是你在不违反你声明的要求的情况下能得到的最好的解决方案。最接近的解决方案是将图像的Build Action设置为Resource,并在第二个源路径中使用application权限,这样可以在设计器和运行时中正确显示图像。

更新:

“Resource”构建操作对于.Net Standard类库不可用。我没有找到任何关于是否将来会支持它的信息。目前,如果你的ResourcesAssembly必须针对.Net Standard,请使用你在问题中描述的第一个变体。

将构建操作设置为资源将使图像文件成为实际的“程序集资源”,最适合关于从程序集中加载图像的问题,或者关于在不同的程序集中的图像的问题。

关于你的问题,我尝试按照你的建议进行操作,但在XAML设计器和WPF应用程序的运行时中仍然无法看到可见的图像。虽然对我来说,第一个变体现在是最合适的,但是我很想知道问题出在哪里。

在你的问题中,评论者正确地指出,选择Resource而不是Embedded Resource。

在.NET Standard 1.4项目类型中没有“Resource”选项,只有“Embedded resource”,我认为在普通的.NET项目类型中,Embedded resource相当于Resource。我说的对吗?

我指定了我的问题,资源库的类型是.NET Standard 1.4。

通过你的解释,我完全明白你的答案了。我困惑于“但是当你使用VS的XAML设计器时,执行的程序集是XDesProc.exe”,我经常在我的设计器属性对我的点击或输入不响应时终止这个进程。现在,我明白了siteoforigin的含义。

0