c# - 您如何在 WPF 中仅检查 Visual Studio 2010 设计器(以便不针对 Blend 的设计器)?

标签 c# wpf visual-studio-2010 visual-studio expression-blend

我发现,在许多情况下,如果 WPF UserControl 包含一个控件根据控件的加载事件(例如转换到通过像 VisualStateManager.GoToState(this, "AfterLoaded", true); 这样的调用来改变视觉状态。

我解决这些设计器崩溃的典型方法是使用 DesignerProperties.GetIsInDesignMode(this) approach在控件的构造函数中:

public MyControl()
{
    // prevent designer crashes
    if (DesignerProperties.GetIsInDesignMode(this))
        return;

    Loaded += MyControlLoaded;
    Unloaded += MyControlUnloaded;
    IsVisibleChanged += MyControlIsVisibleChanged;    
}

这种方法同时针对 Visual Studio 2010 和 Expression Blend 4,使我的设计界面再次可见。但是,它也删除了设计人员可能为我提供的任何设计时预览(例如上面提到的加载事件的 VSM 状态更改)。特别是 Blend,能够在其设计器中为我提供预览(如果我切换到不同的 Blend 选项卡,然后切换回原始选项卡,我会看到加载的动画运行)。此外,对于我尚未应用上述方法的一些控件,Visual Studio 2010 的设计器会崩溃,而 Blend 4 的设计器不会。因此,我想做的是检查 Visual Studio 2010 的设计器,以便我可以让 Blend 的设计器通过并提供其预览功能。

此功能的好处是我不需要经常构建和运行应用程序(查看加载的动画之类的东西),因为 Blend 的设计器可以给我它的预览,从而节省了时间。

最佳答案

我找到了一些有用的东西。这个想法是使用 DesignerProperties.GetIsInDesignMode(...) 方法结合检查运行代码的进程名称

对于我的 VisualStudio 2010,我看到进程名称是“devenv”:

Visual Studio Process name

然后我找到this post这解释了 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 的设计器完全崩溃,因为它无法执行通过调用 VisualStateManager.GoToState(...) 启动的 Storyboard

为了更好地说明这是有效的,我在针对 VS 2010 设计器的 OnApplyTemplate() 代码中将控件的背景属性设置为蓝色(参见屏幕截图)。

    /// 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 控件的背景不是蓝色的)...

Blend 4 designer preview

... 这是 Visual Studio 的设计器向我展示的内容。现在它的设计器没有崩溃,SunkenBorder 控件的背景都是蓝色的......

Visual Studio 2010 designer preview

... 最后,这是运行时的结果(同样,SunkenBorder 控件的背景不是蓝色的):

enter image description here

关于c# - 您如何在 WPF 中仅检查 Visual Studio 2010 设计器(以便不针对 Blend 的设计器)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14610419/

相关文章:

c# - 在 Visual Studio 2012 中的所有源代码文件中插入版权声明/横幅

c# - visual C#2010播放形式1的声音(来自资源文件)

visual-studio-2010 - 从 Visual Studio 2010 中的类自动创建 .cs 文件

c# - 连一个简单的方法都无法内联(?)

c# - StructureMap(或任何 IoC)和 WCF

c# - .NET 将 key 发送到计算器

.net - WPF:绑定(bind)到 ListBoxItem.IsSelected 不适用于屏幕外项目

WPF DataBound ListBox 添加动画但不滚动

c# - WPF DataGridTextColumn 动态代码隐藏

unit-testing - 在MSTest中使用继承