我有不同程序集的图像:
我想将其粘贴到窗口内的应用程序程序集(WPF)中。我尝试了两种变种。
1
<Image Source="pack://siteoforigin:,,,/Common/Images/CompanyLogo.png" />
界面中的图像在运行时可见。但VS的XAML设计师在设计时并没有显示图像,并说这是一个错误:
无法找到路径的一部分&#39; C:\ Program Files(x86)\ Microsoft 视觉 工作室\ 2017 \社区\ Common7 \ IDE \共同\ IMAGES \ CompanyLogo.png&#39;
2
<Image Source="pack://application:,,,/ResourcesAssembly;component/Common/Images/CompanyLogo.png" />
图像在运行时不可见,但在设计时一切正常。
Visual Studio 2017社区版15.4.4。
所以第一个变种似乎适合我,但是这个奇怪的错误 - 为什么它试图在Visual Studio文件夹中找到图像? &#34; siteoforigin&#34;选项与应用程序exe相关,而不是与Visual Studio exe相关,不是吗?
更新
尝试使用构建操作的第二个变体作为&#34;嵌入式资源&#34; (ResourcesAssembly是.NET Standard 1.4项目)。甚至清理并重建了解决方案。结果与第二个变体中的结果相同:图像在运行时不可见,但在设计时它是可见的。
答案 0 :(得分:3)
&#34; siteoforigin&#34;选项涉及应用程序exe,而不是 Visual Studio exe,不是吗?
确实,siteoforigin
指向执行程序集目录。但是当你使用VS的XAML设计器时,从你指定的目录(C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE
)执行程序集是... XDesProc.exe。这就是图片搜索路径为...\IDE\Common\Images\CompanyLogo.png
的原因。
您可以问 - &#34;有没有办法在WPF设计器和应用程序运行时中正确地显示图像?&#34;好吧,如果你想保持两个要求(第一个 - 外部资源装配中的图像,第二个 - 图像集的构建操作设置为&#39;内容&#39;),那么可能没有。至少我无法找到解决方案。
包URI中具有siteorigin
权限的选项不合适,因为图像应该加载到具有不同执行目录的不同应用程序中(参见上文)。
包URI中具有application
权限的选项不适用,因为它仅适用于编译为程序集(本地或引用)的资源文件。这实际上是你在第二个版本中没有在运行时看到图像的原因。
因此,如果第一个版本适合您,那么确定,它是您可以拥有的最好的,同时不违反您声明的要求。允许在Designer和运行时正确查看图像的最近解决方案是将Build Action
设置为Resource
以获取图像,并使用具有application
权限的第二个源路径。 / p>
<强>更新强>
&#34;资源&#34;构建操作不适用于.Net标准类库。我还没有找到任何信息是否会得到支持。目前,如果您的ResourcesAssembly
必须以.Net标准为目标,那么您最好的选择是使用您在问题中描述的第一个变体。
答案 1 :(得分:0)
我对WPF还是很陌生,最近在业余时间从事一个业余项目时,遇到了一个非常相似的问题,受了类似的约束。
尽管如此,正如您已经认识到的那样,application
在设计时可以正常运行,而在运行时则不能,而siteoforigin
则相反。因此,解决此问题的一种合理方法是简单地同时使用siteoforigin
和运行时的application
。
为此,您只需要截取控件的Source
属性的设置即可。一种方法是使用继承。
以下是为 ResourceDictionary 执行此操作的示例:
实施
/// <summary>
/// A modified type of <see cref="ResourceDictionary"/> 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:,,,".
/// </summary>
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;
/// <summary>
/// Gets or sets the design time source.
/// </summary>
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);
}
}
/// <summary>
/// Please use <see cref="RedirectSource"/> instead.
/// </summary>
public new Uri Source
{
get => throw new Exception(UseRedirectSource);
set => throw new Exception(UseRedirectSource);
}
}
用法示例
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<SiteOfOriginResourceDictionary RedirectSource="pack://application:,,,/Theme/Default/Root.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
在实践中,此解决方案对我有用,并且我积极使用此代码。我敢肯定,您可以使用Image
和/或其他WPF组件执行相同的操作。
也就是说,就我而言,我只需要在ResourceDictionary
上提供支持。在您的情况下,此解决方案不是最佳选择,因为您可能(最终)可能需要对以后的多个控件执行此操作。
这样,我将提出一个可能的解决方案,以进一步研究Attached Properties
的使用,并创建一个附加属性来设置控件的Source
,在application
之间切换设计时间和siteoforigin
在运行时。
相反,它可以在多个控件中重复使用,而不必每次都为每个新控件/类继承。
在相关说明中,我不能说我知道为什么将资源的构建操作设置为application
时在设计器中使用Content
的原因。根据文档,当资源“被编译为引用的程序集” (Source)时,将使用此URI,但是仍然对我有用。
这是我在StackOverflow上的第一篇文章,并且是我的爱好者,所以请放轻松。