1. 问题

假设我在Windows10的环境新建一个4.6的WPF项目,添加一个ComboBox,并用Blend在这个ComboBox上右键“编辑模板”->“编辑副本”,Blend不仅帮我创建了模板,还会自动引用PresentationFramework.Aero2这个DLL,即使用Aero2这个主题的资源文件。一切看起来很简单,直接,纯真,善良,但将这个项目放到Windows7环境下运行就会报这样的错误:

“System.IO.FileNotFoundException: 未能加载文件或程序集“PresentationFramework.Aero2, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。系统找不到指定的文件。”

既没做什么丧尽天良的事,也没做什么泯灭人性的操作,然而程序出错了。

2. 原因

先来说说什么是Aero2。

WPF提供了以下几种主题

主题文件 桌面主题
Classic.xaml Windows XP 操作系统上的经典 Windows 外观(Windows 95、Windows 98 和 Windows 2000)。
Luna.NormalColor.xaml Windows XP 上的默认蓝色主题。
Luna.Homestead.xaml Windows XP 上的橄榄色主题。
Luna.Metallic.xaml Windows XP 上的银色主题。
Royale.NormalColor.xaml Windows XP Media Center Edition 操作系统上的默认主题。
Aero.NormalColor.xaml Windows Vista 操作系统上的默认主题。

Windows 8 之后WPF更新了Aero2和AeroLite两种主题,关于Aero、Aero2、AeroLite的区别具体可见这个网页。再之后微软就没有更新WPF主题了

Aero

Aero2

WPF程序启动时大概就是用这段代码确定主题,也就是说默认是Aero,如果在Windows 8 或以上自动转为Aero2:

_themeName = themeName.ToString();
_themeName = Path.GetFileNameWithoutExtension(_themeName); if(String.Compare(_themeName, "aero", StringComparison.OrdinalIgnoreCase) == 0 && Utilities.IsOSWindows8OrNewer)
{
_themeName = "Aero2";
}

所以在Windows 10上使用Blend获取控件模板的副本时Blend识别出当前使用Aero2的主题并主动引用了Aero2相关的资源。

那么为什么在WIndows 7 中使用Aero2会出错呢?用Bing搜一搜答案就出来了:

Problem with assembly PresentationFramework.Aero2

The assembly PresentationFramework.Aero2 in your project is metadata only assembly, which is used in dev time. You can get the full assembly under:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF

Please try to replace with the correct assembly. It should work.

简单来说就是在C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6\PresentationFramework.Aero2.dll这个位置的是个假货(大小为161K)。真货在C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF这个目录下(大小为248K),但WIN7下同个目录找不到Aero2这个DLL。

3. 解决方案

知道问题原因后,要解决这个问题就很简单了,随随便便都能想到3个:

  1. 在Windows10电脑上找到C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.Aero2.dll这个DLL,放到项目中,并在项目中引用这个DLL。

  2. 在Nuget上搜搜Aero2,找个上去像那么回事的,例如这个

  3. 用ILSpy反编译Aero2.dll,把需要的样式复制粘贴到自己的项目中。

简单测试了看上去都没问题,不过,其实,可是我都没有用这三个方案。

4. 实际上根本不需要Aero2?

回到最开始的问题,ComboBox的样式用到Aero2的地方只有Themes:SystemDropShadowChrome这个部分,这用于给弹出菜单提供阴影。而这个类在Aero(不是2)中也有提供,在我记忆里两个DLL中这个类的实现完全一致,将Aero2的引用替换成Aero就可以解决这个问题了。甚至反编译后获取SystemDropShadowChrome的源码自己创建一个也可以。

5. 结语

程序员的开发环境总是用最新的,但客户环境不受控制,最近还听到人抱怨要兼容XP的电脑。我以前面对的客户群体都比较单一所以没有太多兼容性方面的经验,所以这次才踩了这么明显的坑,不知道有没有这方面的完整的指南?

6. 参考

Problem with assembly PresentationFramework.Aero2

Getting Started PresentationTheme Aero

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2fe5qd7iobmso

[WPF]何如在Win7使用Aero2主题的更多相关文章

  1. [WPF自定义控件库]以Button为例谈谈如何模仿Aero2主题

    1. 为什么选择Aero2 除了以外观为卖点的控件库,WPF的控件库都默认使用"素颜"的外观,然后再提供一些主题包.这样做的最大好处是可以和原生控件或其它控件库兼容,而且对于大部分 ...

  2. 让你的WPF程序在Win7下呈现Win8风格主题

    今天在Win8下使用了一个我之前写的一个WPF程序的时候,发现现在也支持Win8效果了(记得以前的.net 4.0的版本是不支持的).由于WPF的控件是自绘的,并不受系统主题所控制,也就是说.net ...

  3. DevExpress WPF v19.1新版亮点:主题/Tree List等控件新功能

    行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部 ...

  4. WPF程序在Windows 7下应用Windows 8主题

    这篇博客介绍如何在Windows 7下应用Windows 8的主题. 首先我们先看一个很常见的场景,同样的WPF程序(样式未重写)在不同的操作系统上展示会有些不同.这是为什么呢?WPF程序启动时会加载 ...

  5. WPF,Silverlight与XAML读书笔记第四十六 - 外观效果之三皮肤与主题

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. 皮肤 皮肤是应用程序中样式与模板的集合,可以 ...

  6. Win7主题被禁用

    今天早上干了一件傻缺的事,打开电脑的时候,某卫士提醒开机速度击败全国0.2%的电脑,之后点了优化...随后就发生了接下来的一幕: win7下面的主题都不能使用了,只能使用那种复古(很丑的样式,看着很不 ...

  7. Win7主题存放路径详解

    WIN7用户主题--- 自定义主题  首先当然是用户自定义的主题文件夹,这个文件夹一般是存放在下面这个路径(注意那个用户名改成你自己的登陆名喔,比如 administrator) C:\Users\用 ...

  8. [WPF自定义控件库]自定义Expander

    1. 前言 上一篇文章介绍了使用Resizer实现Expander简单的动画效果,运行效果也还好,不过只有展开/折叠而缺少了淡入/淡出的动画(毕竟Resizer模仿Expander只是附带的功能).这 ...

  9. [WPF 自定义控件]自定义控件库系列文章

    Kino.Toolkit.Wpf Kino.Toolkit.Wpf是一组简单实用的WPF控件与工具,用于介绍自定义控件的入门.相关博客地址如下: 开始一个自定义控件库项目 介绍开始一个自定义控件库项目 ...

随机推荐

  1. JAVA项目从运维部署到项目开发(一.Jenkins)

    一.Jenkins的介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作, 旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 二.功能 Jen ...

  2. Python——pyHook监听鼠标键盘事件

    pyHook包为Windows中的全局鼠标和键盘事件提供回调. 底层C库报告的信息包括事件的时间,事件发生的窗口名称,事件的值,任何键盘修饰符等. 而正常工作需要pythoncom等操作系统的API的 ...

  3. spring4笔记----依赖注入的两种形式

    设值注入:通过<property.../>元素驱动Spring执行setter的方法 构造注入:通过<constructor-arg.../>元素驱动Spring执行带有参数的 ...

  4. parent.fraInterface.xxxxxx

    fraInterface是自己定义的一个frame的名字,是通过在frame标签中设置name属性实现的.以上那句代码就是通过parent这个公共接口在各个frame间,也就是调用拥有同一个父亲的名为 ...

  5. Should we ban guns 英语禁枪议论文

    Should we ban guns ? 我们应该禁枪吗? 英语议论文 Should we ban guns? Author:Pleiades_Antares(www.cnblogs.com/iris ...

  6. ubuntu下配置rsync,实现远程备份

    rysnc(remote synchronize)在CentOS系统默认安装在/usr/bin,此外rysnc在windows平台下也有相应版本.主页地址为: http://rsync.samba.o ...

  7. Thread.currentThread()和this的区别——《Java多线程编程核心技术》

    前言:在阅读<Java多线程编程核心技术>过程中,对书中程序代码Thread.currentThread()与this的区别有点混淆,这里记录下来,加深印象与理解. 具体代码如下: pub ...

  8. WPF调用zxing生成二维码

    1.登录http://zxingnet.codeplex.com/,下载对应.net版本的zxing库 2.引入zxing.dll 3.新建界面控件 using System; using Syste ...

  9. CentOS 7下安装Python3.6

    CentOS 7下安装Python3.6.4   CentOS 7下安装Python3.5 •安装python3.6可能使用的依赖 yum install openssl-devel bzip2-de ...

  10. centos7下安装docker(23.docker-swarm之如何访问service)

    如何访问service呢? 为了便于分析,我们重新部署web-server 1.删除service 执行命令docker service rm web-server docker service rm ...