有没有办法检查 WPF 当前是否在设计模式下执行?

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

它看起来像这样:

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

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

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

目前,我解决这个问题的方法是让设计人员在进行工作之前,进入 ViewModel 并更改“ ApplicationDevelopmentMode”。“执行”到“应用开发模式”。设计”:

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);
}
}
}
70879 次浏览

你可以这样做:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

我相信您正在寻找 GetIsInDesignMode,它采用 DependencyObject。

我。

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

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

DesignerProperties.IsInDesignTool

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

Windows.ApplicationModel.DesignMode.DesignModeEnabled

当 VisualStudio 为我自动生成一些代码时,它使用

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

如果你在你的大型 WPF/Silverlight/WP8/WinRT应用程序中广泛使用 卡利本,微型,你可以在你的视图模型中使用方便的和 通用的 Caliburn 的 Execute.InDesignMode静态属性(在 Blend 中和 Visual Studio 中一样好) :

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"
//};
}
}
public static bool InDesignMode()
{
return !(Application.Current is App);
}

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

在 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"

我只在 Visual Studio 2013和.NET 4.5中测试过,但它确实有效。

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

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

这种方法的好处是它不需要特定的 App类的外显知识,并且可以在整个代码中全局使用。特别是用虚拟数据填充视图模型。

如果你的类不需要一个空的构造函数,我有个主意。

其思想是创建一个空的构造函数,然后用 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

还有一个问题:

<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>

result of the above code

如果 真的需要其他东西的空构造函数,那么这种方法就不起作用。

接受的答案不适合我(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");
}
}