Есть ли способ проверить, работает ли 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>
![результат вышеуказанного кода]()
Это не сработает, если вам действительно нужен пустой конструктор для чего-то другого.