Есть ли способ проверить, выполняется ли WPF в настоящее время в режиме разработки или нет?
кто-нибудь знает некоторую глобальную переменную состояния, которая доступна, чтобы я мог проверить, выполняется ли код в настоящее время в режиме разработки (например, в Blend или Visual Studio) или нет?
это будет выглядеть примерно так:
//pseudo code:
if (Application.Current.ExecutingStatus == ExecutingStatus.DesignMode)
{
...
}
причина, по которой мне это нужно: когда мое приложение отображается в режиме дизайна в Expression Blend, я хочу, чтобы ViewModel вместо этого использовал "класс клиента дизайна" , в котором есть макет данных, которые дизайнер может просмотреть в режиме конструктора.
однако, когда приложение фактически выполняется, я, конечно, хочу, чтобы ViewModel использовал реальный класс Customer, который возвращает реальные данные.
В настоящее время я решаю это, имея дизайнера, прежде чем он работает над ним, зайдите в ViewModel и измените "ApplicationDevelopmentMode.Выполнение "to" ApplicationDevelopmentMode.Проектирование":
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 ответов
Я считаю, что вы ищете GetIsInDesignMode, который принимает DependencyObject.
Ie.
// 'this' is your UI element
DesignerProperties.GetIsInDesignMode(this);
Edit: при использовании Silverlight / WP7 вы должны использовать IsInDesignTool
С GetIsInDesignMode
иногда может возвращать false в Visual Studio:
DesignerProperties.IsInDesignTool
Edit: и, наконец, в интересах полноты, эквивалент в приложениях WinRT / Metro / Windows Store является DesignModeEnabled
:
Windows.ApplicationModel.DesignMode.DesignModeEnabled
public static bool InDesignMode()
{
return !(Application.Current is App);
}
работает из любого места. Я использую его, чтобы остановить воспроизведение видео databound в дизайнере.
когда Visual Studio автоматически сгенерировал для меня код, он использовал
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
...
}
и если вы активно используете Калибурн.Микро!--4--> для 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"
//};
}
}
есть другие (возможно, более новые) способы указания данных времени разработки в 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"
Я тестировал это только с 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
class и что его можно использовать глобально по всему коду. В частности, для заполнения моделей представления фиктивными данными.
у меня есть идея для вас, если ваш класс не нужен пустой конструктор.
идея состоит в том, чтобы создать пустой конструктор, а затем пометить его 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>
это не будет работать, если вы действительно нужен пустой конструктор для чего-то другого.