157

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

它看起来像这样:

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

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

但是,当应用程序实际执行时,我当然希望 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);
        }
    }
}
4

9 回答 9

244

我相信您正在寻找GetIsInDesignMode,它需要一个 DependencyObject。

IE。

// '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
于 2009-05-07T12:20:43.823 回答
130

你可以这样做:

DesignerProperties.GetIsInDesignMode(new DependencyObject());
于 2009-05-07T12:19:18.630 回答
29
public static bool InDesignMode()
{
    return !(Application.Current is App);
}

随时随地工作。我用它来阻止数据绑定视频在设计器中播放。

于 2013-11-14T13:39:51.743 回答
10

如相关答案中所述,还有其他(可能是较新的)方法可以在 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" 
于 2014-07-21T21:28:29.257 回答
9

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

if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) 
{
    ...
}
于 2012-07-27T15:37:25.693 回答
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"
        //};
    }
}
于 2013-11-12T13:26:05.427 回答
4

接受的答案对我不起作用(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");
        }
    }
于 2019-08-16T07:41:23.623 回答
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类的明确知识,并且可以在整个代码中全局使用。专门用虚拟数据填充视图模型。

于 2015-08-26T12:04:20.757 回答
2

如果您的类不需要空的构造函数,我有一个想法。

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

上述代码的结果

如果您真的需要空构造函数来做其他事情,这将不起作用。

于 2015-10-08T16:10:37.593 回答