Есть ли способ проверить, выполняется ли в настоящее время WPF в режиме разработки или нет? - PullRequest
134 голосов
/ 07 мая 2009

Кто-нибудь знает какую-нибудь глобальную переменную состояния, которая доступна, чтобы я мог проверить, выполняется ли код в настоящее время в режиме разработки (например, в Blend или Visual Studio) или нет?

Это будет выглядеть примерно так:

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

Причина, по которой мне это нужно, заключается в том, что когда мое приложение отображается в режиме разработки в Expression Blend, я хочу, чтобы 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);
        }
    }
}

Ответы [ 8 ]

210 голосов
/ 07 мая 2009

Я полагаю, вы ищете 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
107 голосов
/ 07 мая 2009

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

DesignerProperties.GetIsInDesignMode(new DependencyObject());
23 голосов
/ 14 ноября 2013
public static bool InDesignMode()
{
    return !(Application.Current is App);
}

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

9 голосов
/ 27 июля 2012

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

if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) 
{
    ...
}
8 голосов
/ 22 июля 2014

Существуют другие (возможно, более новые) способы указания данных времени разработки в 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 голосов
/ 12 ноября 2013

А если вы широко используете Caliburn.Micro для своего большого WPF / Silverlight / WP8 / WinRT приложения, вы можете использовать удобные и универсальные калибровочные Execute.InDesignMode статическое свойство в ваших view-моделях (и оно работает в 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"
        //};
    }
}
2 голосов
/ 26 августа 2015

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

1 голос
/ 08 октября 2015

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

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

result of the above code

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

...