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

时间:2009-05-07 12:10:28

标签: c# wpf expression-blend

是否有人知道某些可用的全局状态变量,以便我可以检查代码当前是否在设计模式下执行(例如在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);
        }
    }
}

9 个答案:

答案 0 :(得分:209)

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

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

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

DesignerProperties.IsInDesignTool

编辑最后,为了完整起见,WinRT / Metro / Windows应用商店应用中的等价物为DesignModeEnabled

Windows.ApplicationModel.DesignMode.DesignModeEnabled

答案 1 :(得分:106)

您可以这样做:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

答案 2 :(得分:23)

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

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

答案 3 :(得分:9)

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

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

答案 4 :(得分:8)

还有其他(可能更新)的方法在WPF中指定设计时数据,mentioned in this related answer

基本上,您可以使用design-time instance of your ViewModel

指定设计时数据
d:DataContext="{d:DesignInstance Type=v:MySampleData, IsDesignTimeCreatable=True}"

specifying sample data in a XAML file

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="...">

在运行时,所有的&#34; d:&#34;设计时标签消失,因此您只能获得运行时数据上下文,但是您选择设置它。

修改 您可能还需要这些行(我不确定,但它们似乎相关):

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

答案 5 :(得分:7)

如果您在大型 WPF / Silverlight / WP8 / WinRT 应用程序中广泛使用Caliburn.Micro,则可以使用方便且通用校准的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"
        //};
    }
}

答案 6 :(得分: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类,并且可以在整个代码中全局使用。特别是用虚拟数据填充视图模型。

答案 7 :(得分: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");
        }
    }

答案 8 :(得分:1)

如果你的班级不需要空的构造函数,我有一个想法。

想法是创建一个空构造函数,然后使用ObsoleteAttribute标记它。设计者忽略了过时的属性,但是如果你试图使用它,编译器会引发错误,因此不存在意外使用它的风险。

pardon my visual basic

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>

result of the above code

如果确实需要空构造函数来处理其他内容,这将无效。