有没有办法来检查WPF当前是否在devise模式下执行?
有谁知道一些可用的全局状态variables,以便我可以检查代码当前是否在devise模式下执行(例如在Blend或Visual Studio中)?
它看起来像这样:
//pseudo code: if (Application.Current.ExecutingStatus == ExecutingStatus.DesignMode) { ... }
我需要的原因是:当我的应用程序在Expression Blend中以devise模式显示时,我希望ViewModel改为使用“Design Customer类”,其中包含模拟数据的devise人员可以在devise模式下查看的数据。
但是,当应用程序正在执行时,我当然希望ViewModel使用返回实际数据的真实Customer类。
目前我通过devise人员解决这个问题,在他开始工作之前,进入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); } } }
我相信你正在寻找GetIsInDesignMode ,它采用了一个DependencyObject。
IE浏览器。
// 'this' is your UI element DesignerProperties.GetIsInDesignMode(this);
编辑:当使用Silverlight / WP7时,你应该使用IsInDesignTool
因为在Visual Studio中,有时候GetIsInDesignMode
会返回false:
DesignerProperties.IsInDesignTool
编辑:最后,为了完整性,WinRT / Metro / Windows Store应用程序中的等效function是DesignModeEnabled
:
Windows.ApplicationModel.DesignMode.DesignModeEnabled
你可以做这样的事情:
DesignerProperties.GetIsInDesignMode(new DependencyObject());
public static bool InDesignMode() { return !(Application.Current is App); }
从任何地方工作。 我用它来阻止devise器中播放的数据绑定video。
当Visual Studio自动生成一些代码使用它
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { ... }
如果你为你的大型WPF / Silverlight / WP8 / WinRT应用程序广泛使用Caliburn.Micro ,你可以在你的视图模型中使用方便和通用的 caliburn Execute.InDesignMode
静态属性(并且它在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中指定devise时数据的其他(也许更新的)方法。
本质上,您可以使用ViewModel的devise时实例指定devise时数据:
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:”devise时标签都消失了,所以你只能得到你的运行时数据上下文,但是你select设置它。
编辑您可能还需要这些行(我不确定,但他们似乎相关):
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
我只用Visual Studio 2013和.NET 4.5testing过,但是这个技巧。
public static bool IsDesignerContext() { var maybeExpressionUseLayoutRounding = Application.Current.Resources["ExpressionUseLayoutRounding"] as bool?; return maybeExpressionUseLayoutRounding ?? false; }
虽然Visual Studio中的某些设置可能会将此值更改为false,但如果发生这种情况,我们可能只会检查此资源名是否存在。 当我在devise器外部运行我的代码时,它是null
的。
这种方法的好处是,它不需要明确知道具体的App
类,它可以在整个代码中使用。 特别是用虚拟数据填充视图模型。
我有一个想法,如果你的类不需要一个空的构造函数。
这个想法是创build一个空的构造函数,然后用ObsoleteAttribute标记它。 devise者忽略了过时的属性,但是如果你尝试使用它,编译器会产生一个错误,所以没有意外的使用它的风险。
(请原谅我的视觉基础 )
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>
如果你确实需要其他的空构造函数,这将不起作用。