我发现了一些有用的东西。这个想法是使用DesignerProperties.GetIsInDesignMode(...)
结合检查运行代码的进程名称的方法。
对于我的 VisualStudio 2010,我看到进程名称是“devenv”:
然后我发现这篇文章解释System.Diagnostics.Process
了我们需要获得的过程信息。知道了这一点,我创建了这个辅助方法:
private bool IsVisualStudio2010DesignerRunning()
{
using (var process = System.Diagnostics.Process.GetCurrentProcess())
{
const string visualStudio2010ProcessName = "devenv";
if (process.ProcessName.ToLowerInvariant().Contains(visualStudio2010ProcessName)
&& DesignerProperties.GetIsInDesignMode(this))
{
return true;
}
else
return false;
}
}
为了说明这是有效的,这里是它的应用示例
它在我编写的名为 SunkenBorder 的自定义控件中。这个控件有一个行为,它在第一次机会时转换到某个 VisualState,因此这个状态是用户看到的初始状态。此代码在OnApplyTemplate()
覆盖中执行。Expression Blend 4 能够在运行时处理和显示它。另一方面,Visual Studio 2010 的设计器完全崩溃,因为它无法执行Storyboard
调用VisualStateManager.GoToState(...)
.
为了更好地说明这是有效的,我在OnApplyTemplate()
针对 VS 2010 设计器的代码中将控件的背景属性设置为蓝色(参见屏幕截图)。
/// Non-static constructor
public SunkenBorder()
{
// Avoid Visual Studio 2010 designer errors
if (IsVisualStudio2010DesignerRunning())
return;
// Expression Blend 4's designer displays previews of animations
// that these event handlers initiate!
Initialized += new EventHandler(SunkenBorder_Initialized);
Loaded += new RoutedEventHandler(SunkenBorder_Loaded);
Unloaded += new RoutedEventHandler(SunkenBorder_Unloaded);
IsVisibleChanged += new DependencyPropertyChangedEventHandler(SunkenBorder_IsVisibleChanged);
}
// ...
/// Used to set the initial VSM state (its the first opportunity).
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (IsVisualStudio2010DesignerRunning())
{
// set a property just to illustrate that this targets only Visual Studio 2010:
this.Background = Brushes.Blue;
// return before doing VisualState change so Visual Studio's designer won't crash
return;
}
// Blend 4 executes this at design-time just fine
VisualStateManager.GoToState(this, "InitialState", false);
// ...
}
这是 Expression Blend 4 的预览效果(注意 SunkenBorder 控件的背景不是蓝色的)...
...这就是 Visual Studio 的设计师向我展示的内容。现在它的设计器没有崩溃,并且 SunkenBorder 控件的背景都是蓝色的......
...最后,这是运行时的结果(同样,SunkenBorder 控件的背景不是蓝色的):