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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/834283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:30:22  来源:igfitidea点击:

Is there a way to check if WPF is currently executing in design mode or not?

c#wpfexpression-blend

提问by Edward Tanguay

Does anyone know of some global state variable that is available so that I can check if the code is currently executing in design mode (e.g. in Blend or Visual Studio) or not?

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

It would look something like this:

它看起来像这样:

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

The reason I need this is: when my application is being shown in design mode in Expression Blend, I want the ViewModel to instead use a "Design Customer class" which has mock data in it that the designer can view in design mode.

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

However, when the application is actually executing, I of course want the ViewModel to use the real Customer class which returns real data.

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

Currently I solve this by having the designer, before he works on it, go into the ViewModel and change "ApplicationDevelopmentMode.Executing" to "ApplicationDevelopmentMode.Designing":

目前我通过让设计师解决这个问题,在他开始工作之前,进入 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);
        }
    }
}

采纳答案by Richard Szalay

I believe you are looking for GetIsInDesignMode, which takes a DependencyObject.

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

Ie.

IE。

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

Edit:When using Silverlight / WP7, you should use IsInDesignToolsince GetIsInDesignModecan sometimes return false while in Visual Studio:

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

DesignerProperties.IsInDesignTool

Edit:And finally, in the interest of completeness, the equivalent in WinRT / Metro / Windows Store applications is DesignModeEnabled:

编辑:最后,为了完整起见,WinRT / Metro / Windows Store 应用程序中的等效项是DesignModeEnabled

Windows.ApplicationModel.DesignMode.DesignModeEnabled

回答by Sacha Bruttin

You can do something like this:

你可以这样做:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

回答by Darren

When Visual Studio auto generated some code for me it used

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

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

回答by Sevenate

And if you extensively use Caliburn.Microfor your large WPF / Silverlight / WP8 / WinRTapplication you could use handy and universalcaliburn's Execute.InDesignModestatic property in your view-models as well (and it works in Blend as good as in Visual Studio):

如果您在大型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"
        //};
    }
}

回答by Patrick

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

Works from anywhere. I use it to stop databound videos from playing in the designer.

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

回答by cod3monk3y

There are other (maybe newer) ways of specifying design-time data in WPF, as mentioned in this related answer.

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

Essentially, you can specify design-time data using a design-time instance of your ViewModel:

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

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

or by specifying sample data in a XAML file:

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

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

You have to set the SamplePage.xamlfile properties to:

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

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

I place these in my UserControltag, like this:

我将这些放在我的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="...">

At run-time, all of the "d:" design-time tags disappear, so you'll only get your run-time data context, however you choose to set it.

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

EditYou may also need these lines (I'm not certain, but they seem relevant):

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

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

回答by John Leidegren

I've only tested this with Visual Studio 2013 and .NET 4.5 but it does the trick.

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

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

It's possible though that some setting in Visual Studio will change this value to false, if that ever happens we can result to just checking whether this resource name exist. It was nullwhen I ran my code outside the designer.

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

The upside of this approach is that it does not require explicit knowledge of the specific Appclass and that it can be used globally throughout your code. Specifically to populate view models with dummy data.

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

回答by DonkeyMaster

I have an idea for you if your class doesn't need an empty constructor.

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

The idea is to create an empty constructor, then mark it with ObsoleteAttribute. The designer ignores the obsolete attribute, but the compiler will raise an error if you try to use it, so there's no risk of accidentaly using it yourself.

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

(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

And the xaml:

和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

上面代码的结果

This won't work if you reallyneed the empty constructor for something else.

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

回答by Ger Hobbelt

Accepted answer didn't work for me (VS2019).

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

After inspecting what was going on, I came up with this:

在检查了发生了什么之后,我想出了这个:

    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");
        }
    }