IT story

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

hot-time 2020. 6. 23. 07:22
반응형

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


코드가 현재 디자인 모드 (예 : 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);
        }
    }
}

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

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

DesignerProperties.GetIsInDesignMode(new DependencyObject());

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

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


Visual Studio가 자동으로 나를 위해 일부 코드를 생성했을 때

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

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

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

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

or by specifying sample data in a XAML file:

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

You have to set the SamplePage.xaml file properties to:

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

I place these in my UserControl tag, like this:

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

Edit You 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" 

And if you extensively use Caliburn.Micro for your large WPF / Silverlight / WP8 / WinRT application you could use handy and universal caliburn's Execute.InDesignMode static property in your view-models as well (and it works in Blend as good as in 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"
        //};
    }
}

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

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 null when I ran my code outside the designer.

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


Accepted answer didn't work for me (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");
        }
    }

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.

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

<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 really need the empty constructor for something else.

참고URL : https://stackoverflow.com/questions/834283/is-there-a-way-to-check-if-wpf-is-currently-executing-in-design-mode-or-not

반응형