WPF가 현재 디자인 모드에서 실행 중인지 확인하는 방법이 있습니까?


147

코드가 현재 디자인 모드 (예 : Blend 또는 Visual Studio)에서 실행 중인지 확인할 수 있도록 사용 가능한 전역 상태 변수를 아는 사람이 있습니까?

다음과 같이 보일 것입니다 :

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

내가 필요한 이유는 : Expression Blend에서 응용 프로그램이 디자인 모드로 표시 될 때 디자이너가 디자인 모드에서 볼 수있는 모의 데이터가있는 "Design Customer 클래스"를 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);
        }
    }
}

답변:


226

DependencyObject를 사용하는 GetIsInDesignMode를 찾고 있다고 생각합니다 .

즉.

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

편집 : Silverlight / WP7을 사용하는 경우 Visual Studio에서 때때로 false를 반환 할 수 IsInDesignTool있으므로 사용해야합니다 GetIsInDesignMode.

DesignerProperties.IsInDesignTool

편집 : 마지막으로, 완성도를 높이기 위해 WinRT / Metro / Windows Store 응용 프로그램의 해당 기능은 DesignModeEnabled다음과 같습니다.

Windows.ApplicationModel.DesignMode.DesignModeEnabled

3
참고로 IsInDesignMode는 실제로 연결된 속성이므로 xaml의 바인딩에서도 사용할 수 있습니다. 비록 가장 일반적인 용도는 아닐 수도 있습니다 :)
aL3891

3
WinRT 및 WP와 같은 최신 XAML "응용 프로그램"을 사용하여 답변을 최신 상태로 유지해 주셔서 감사합니다.
Sevenate

VS2019에서는 스위치 Enable project code가 활성화되어 있어야합니다 (또는 메뉴-> 디자인-> 🗹 프로젝트 코드 실행).
marbel82

115

다음과 같이 할 수 있습니다 :

DesignerProperties.GetIsInDesignMode(new DependencyObject());

30
이 방법은 또한 ViewModels를 디자이너 친화적으로 만드는 데 효과적입니다 (DependencyObjects 자체가 아니기 때문에).
Pat

1
DependencyObject에는 보호 된 생성자가 internal class MyDependencyObject : DependencyObject {}있습니다. new MyDependencyObject대신 정의 하고 사용하십시오.DependencyObject
Rico Suter


뷰 모델에서이 작업을 수행하는 경우이를 정적 클래스로 추상화하고 결과를 정적 부울로 저장하려고합니다.
Simon_Weaver

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

어디서나 작동합니다. 데이터 바인딩 된 비디오가 디자이너에서 재생되지 않도록하는 데 사용합니다.


위의 변형 Application.Current.MainWindow == null은 형식 테스트가 더 좋고 더 직접적입니다. 또한 Visual Studio에서 호스팅되는 디자이너가 리소스를 추가하는 것처럼 보이므로 여기에 다른 방법이 있습니다 ( App코드를 호스팅하는 라이브러리 의 특정 유형에 액세스 할 수없는 경우 ) ((bool)Application.Current.Resources["ExpressionUseLayoutRounding"]). 리소스가 없지만 디자이너 컨텍스트에서 작동하는지 확인해야합니다.
John Leidegren

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 를 광범위하게 사용하는 경우 뷰 모델에서도 편리하고 보편적 인 캘리 브릭의 정적 속성을 사용할 수 있습니다 (Visual Studio에서와 마찬가지로 Blend에서도 잘 작동 함).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>

위 코드의 결과

다른 무언가를 위해 빈 생성자가 실제로 필요한 경우 작동하지 않습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.