有没有一种方法可以检查WPF当前是否在设计模式下执行?


146

有谁知道一些可用的全局状态变量,以便我可以检查代码当前是否正在设计模式下执行(例如在Blend或Visual Studio中)?

它看起来像这样:

//pseudo code:
if (Application.Current.ExecutingStatus == ExecutingStatus.DesignMode) 
{
    ...
}

我需要这样做的原因是:当我的应用程序在Expression Blend中以设计模式显示时,我希望ViewModel改为使用其中包含模拟数据的“ Design Customer类”,设计人员可以在设计模式下查看。

但是,当应用程序实际执行时,我当然希望ViewModel使用返回真实数据的真实Customer类。

目前,我可以通过让设计者着手解决这个问题,在他进行设计之前,先进入ViewModel并将“ ApplicationDevelopmentMode.Executing”更改为“ ApplicationDevelopmentMode.Designing”:

public CustomersViewModel()
{
    _currentApplicationDevelopmentMode = ApplicationDevelopmentMode.Designing;
}

public ObservableCollection<Customer> GetAll
{
    get
    {
        try
        {
            if (_currentApplicationDevelopmentMode == ApplicationDevelopmentMode.Developing)
            {
                return Customer.GetAll;
            }
            else
            {
                return CustomerDesign.GetAll;
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
}

Answers:


226

我相信您正在寻找带有DependencyObject的GetIsInDesignMode

就是

// 'this' is your UI element
DesignerProperties.GetIsInDesignMode(this);

编辑:使用Silverlight / WP7时,应使用,IsInDesignTool因为GetIsInDesignMode有时在Visual Studio中可能返回false:

DesignerProperties.IsInDesignTool

编辑:最后,出于完整性考虑,WinRT / Metro / Windows Store应用程序中的等效项是DesignModeEnabled

Windows.ApplicationModel.DesignMode.DesignModeEnabled

3
另外,IsInDesignMode实际上是一个附加属性,因此您也可以在xaml的绑定中使用它。可能不是最常用的方法:)
aL3891 2011年

3
感谢您使用最新的XAML“应用程序”(如WinRT和WP)使答案保持最新。
Sevenate

在VS2019中,Enable project code必须启用开关(或菜单->设计->🗹运行项目代码)。
marbel82

114

您可以执行以下操作:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

30
此方法还可以使ViewModels设计为设计者友好的(因为它们本身不是DependencyObjects)。
帕特

1
DependencyObject的有一个受保护的构造-定义internal class MyDependencyObject : DependencyObject {}使用,new MyDependencyObject而不是DependencyObject
波多黎各苏特


如果在视图模型中执行此操作,则可能需要将其抽象为静态类并将结果存储为静态布尔值
Simon_Weaver

24
public static bool InDesignMode()
{
    return !(Application.Current is App);
}

可在任何地方工作。我用它来阻止数据绑定视频在设计器中播放。


Application.Current.MainWindow == null尽管我喜欢类型测试更好,更直接,但是上面有一个变化。似乎还好像Visual Studio中托管的设计器添加了资源,因此这是另一种方式(如果您无权访问App托管代码的库中的特定类型)((bool)Application.Current.Resources["ExpressionUseLayoutRounding"])。需要检查资源是否不存在,但可以在设计器上下文中使用。
约翰·莱德格伦

9

当Visual Studio自动为我生成一些代码时

if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) 
{
    ...
}

9

本相关答案所述,还有其他(可能是较新的)方法可以在WPF中指定设计时数据。

本质上,您可以使用ViewModel设计时实例来指定设计时数据:

d:DataContext="{d:DesignInstance Type=v:MySampleData, IsDesignTimeCreatable=True}"

或通过在XAML文件中指定示例数据

d:DataContext="{d:DesignData Source=../DesignData/SamplePage.xaml}">

您必须将SamplePage.xaml文件属性设置为:

BuildAction:               DesignData
Copy to Output Directory:  Do not copy
Custom Tool:               [DELETE ANYTHING HERE SO THE FIELD IS EMPTY]

我将它们放在UserControl标签中,如下所示:

<UserControl
    ...
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    ...
    d:DesignWidth="640" d:DesignHeight="480"
    d:DataContext="...">

在运行时,所有“ d:”设计时标记都消失了,因此您只能获得运行时数据上下文,但是可以选择设置它。

编辑 您可能还需要以下几行(我不确定,但它们似乎相关):

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 

7

而且,如果您在大型WPF / Silverlight / WP8 / WinRT应用程序中广泛使用Caliburn.Micro,则还可以在视图模型中使用方便且通用的 caliburn 静态属性(它在Blend中的工作方式与在Visual Studio中一样好):Execute.InDesignMode

using Caliburn.Micro;

// ...

/// <summary>
/// Default view-model's ctor without parameters.
/// </summary>
public SomeViewModel()
{
    if(Execute.InDesignMode)
    {
        //Add fake data for design-time only here:

        //SomeStringItems = new List<string>
        //{
        //  "Item 1",
        //  "Item 2",
        //  "Item 3"
        //};
    }
}

2

我仅使用Visual Studio 2013和.NET 4.5对此进行了测试,但确实可以解决问题。

public static bool IsDesignerContext()
{
  var maybeExpressionUseLayoutRounding =
    Application.Current.Resources["ExpressionUseLayoutRounding"] as bool?;
  return maybeExpressionUseLayoutRounding ?? false;
}

尽管Visual Studio中的某些设置可能会将此值更改为false,但是如果发生这种情况,我们可以仅检查此资源名称是否存在。那是null我在设计器外运行代码的时候。

这种方法的优点是它不需要特定App类的明确知识,并且可以在整个代码中全局使用。专门用虚拟数据填充视图模型。


2

接受的答案对我不起作用(VS2019)。

在检查发生了什么之后,我想到了:

    public static bool IsRunningInVisualStudioDesigner
    {
        get
        {
            // Are we looking at this dialog in the Visual Studio Designer or Blend?
            string appname = System.Reflection.Assembly.GetEntryAssembly().FullName;
            return appname.Contains("XDesProc");
        }
    }

这对我有用,我需要知道我是否在设计时从viewModel内部运行并且无法使用Windows库。我知道这只是一个很小的反映,但是我不喜欢它在生产中运行的想法,因此我将这段代码包装在#if DEBUGelse return false中。有什么理由不这样做吗?
Toby Smith,

1

如果您的课程不需要空的构造函数,我有个主意。

这个想法是创建一个空的构造函数,然后用ObsoleteAttribute对其进行标记。设计器将忽略过时的属性,但是如果您尝试使用该属性,则编译器将引发错误,因此您自己没有偶然使用它的风险。

原谅我的视觉基础

Public Class SomeClass

    <Obsolete("Constructor intended for design mode only", True)>
    Public Sub New()
        DesignMode = True
        If DesignMode Then
            Name = "Paula is Brillant"
        End If
    End Sub

    Public Property DesignMode As Boolean
    Public Property Name As String = "FileNotFound"
End Class

和xaml:

<UserControl x:Class="TestDesignMode"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:vm="clr-namespace:AssemblyWithViewModels;assembly=AssemblyWithViewModels"
             mc:Ignorable="d" 
             >
  <UserControl.Resources>
    <vm:SomeClass x:Key="myDataContext" />
  </UserControl.Resources>
  <StackPanel>
    <TextBlock d:DataContext="{StaticResource myDataContext}" Text="{Binding DesignMode}" Margin="20"/>
    <TextBlock d:DataContext="{StaticResource myDataContext}" Text="{Binding Name}" Margin="20"/>
  </StackPanel>
</UserControl>

以上代码的结果

如果您确实需要空构造函数来执行其他操作,则此方法将无效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.