Есть ли способ проверить, работает ли WPF в режиме разработки или нет?

Кто-нибудь знает какую-либо глобальную переменную состояния, которая доступна, чтобы я мог проверить, выполняется ли код в настоящее время в режиме разработки (например, в 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);
        }
    }
}

Ответ 1

Я считаю, что вы ищете GetIsInDesignMode, который принимает объект DependencyObject.

Т.е.

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

Изменить: При использовании Silverlight/WP7 вы должны использовать IsInDesignTool, так как GetIsInDesignMode может иногда возвращаться false в Visual Studio:

DesignerProperties.IsInDesignTool

Изменить: И, наконец, в интересах полноты эквивалент в приложениях WinRT/Metro/Windows Store DesignModeEnabled:

Windows.ApplicationModel.DesignMode.DesignModeEnabled

Ответ 2

Вы можете сделать что-то вроде этого:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

Ответ 3

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

Работает где угодно. Я использую его, чтобы прекратить воспроизведение видео в формате databound в дизайнере.

Ответ 4

Когда Visual Studio автоматически создала код для меня, он использовал

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

Ответ 5

И если вы широко используете Caliburn.Micro для своего большого приложения WPF/Silverlight/WP8/WinRT, вы можете используйте удобное и универсальное caliburn Execute.InDesignMode статическое свойство в ваших моделях просмотра (и оно работает в Blend так же хорошо, как в Visual Studio):

using Caliburn.Micro;

// ...

/// <summary>
/// Default view-model 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

Существуют другие (возможно, более новые) способы указания данных времени разработки в 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:" исчезают, поэтому вы получите только контекст данных во время выполнения, однако вы решите установить его.

Edit Вам также могут понадобиться эти строки (я не уверен, но они кажутся релевантными):

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

Ответ 7

Я тестировал это только с помощью 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 и что его можно использовать глобально во всем коде. В частности, для заполнения моделей представлений с фиктивными данными.

Ответ 8

У меня есть идея для вас, если вашему классу не нужен пустой конструктор.

Идея состоит в том, чтобы создать пустой конструктор, а затем пометить его с помощью 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>

результат вышеуказанного кода

Это не сработает, если вам действительно нужен пустой конструктор для чего-то другого.