在WPF中显示一张图片,本是一件再简单不过的事情。一张图片,一行XAML代码即可。
但是前段时间遇到了一件奇怪的事:
开发机上运行正常的程序,在某些客户机器上却显示不了图片,而且除了这个问题,其它运行情况都正常。开始排查问题吧,先检查代码,然后检查编译打包过程,并没有发现任何问题。再然后去客户机器上测试,对应路径下的图片是否存在,是否图片所在路径的读写有问题,还是没有发现问题。最后发现,当程序移到其它路径的时候,就一切正常了。而出现错误的路径是:D:\\C#\\ 。这就是今天想说的问题,某些特殊符号(或叫保留字符)对图片显示的影响。
首先简单回顾一下WPF中显示图片常用的两种图片资源存储方式:资源 和 内容。资源会被编译到exe或dll中,使用优势是速度,简便。而内容是与exe或dll有显式关联的独立文件,他的使用优势是灵活。简单介绍这么几句,相信大家都已经很了解了。而我的项目因为经常需要用户自己替换图片资源文件,所以选择了“内容”的方式。
在WPF中,不管是资源还是内容的方式,都是通过URI (uniform resource identifier)来标识和加载文件的。大家可以在这里对URI的构造和解析原理做更多的了解:MSDN WPF 中的 Pack URI。而Pack URI 方案由OPC (Open Packaging Conventions)规范使用,该规范利用了RFC 2396的扩展性来定义Pack URI方案。也就是说我们定义的URI必须符合RFC 2396的规定。
Pack URI 的授权组件是一个嵌入式 URI,它指向程序包并且必须符合 RFC 2396。 另外,必须用字符“,”替换字符“/”,并且必须对保留字符(如“%”和“?”)进行转义。 有关详细信息,请参见 OPC。
那咱们就来看看这个RFC 2396 中到底对URI做了哪些规定和限制:
先来看一下保留字符:reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 。顾名思义,这些字符是预留给系统使用的,我们自己的资源URI里不能包含。
再看看哪些字符是被排除的:excluded = "<" | ">" | "#" | "%" | <"> 。这些字符是不允许出现的,来看看RFC 2396中对这几个字符被排除的解释吧:
The angle-bracket "<" and ">" and double-quote (") characters are excluded because they are often used as the delimiters
around URI in text documents and protocol fields. The character "#" is excluded because it is used to delimit a URI from a fragment identifier in URI references (Section 4). The percent character "%" is excluded because it is used for the encoding of escaped characters.
看到这里就很明显了,我们的图片因为项目路径的关系,包含了“#”符号,而图片又使用了内容的方式,导致URI解析失败,图片没有显示。
虽然我们自己只写了一行XAML代码去实现图片显示,但是WPF的Pack URI做了资源分类,解析和文件加载等。
好了,到此为止就已经很明确的知道了导致错误的原因了,但是暂时还没想到解决办法,只能告诉用户去规范目录命名,如果哪位有解决办法,欢迎回复赐教,感谢!