WPFが現在デザインモードで実行されているかどうかを確認する方法はありますか?


147

コードが現在デザインモード(BlendやVisual Studioなど)で実行されているかどうかを確認できるように、利用可能なグローバル状態変数を知っている人はいますか?

次のようになります。

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

これが必要な理由は、Expression Blendでアプリケーションをデザインモードで表示しているときに、デザイナーがデザインモードで表示できるモックデータを含む「Design Customerクラス」を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);
        }
    }
}

回答:


226

DependencyObject を受け取るGetIsInDesignModeを探していると思います。

つまり。

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

編集: Silverlight / WP7を使用する場合は、Visual Studioでfalseを返すことがあるIsInDesignToolので、使用する必要GetIsInDesignModeがあります。

DesignerProperties.IsInDesignTool

編集:そして最後に、完全を期すために、WinRT / Metro / Windows Storeアプリケーションでの同等のものはDesignModeEnabled次のとおりです。

Windows.ApplicationModel.DesignMode.DesignModeEnabled

3
補足として、IsInDesignModeは実際には添付プロパティなので、xamlからのバインディングでも使用できます。ただし、最も一般的な用途ではないかもしれません:)
aL3891

3
WinRTやWPなどの最新のXAML "アプリケーション"で回答を最新の状態に維持していただきありがとうございます。
2013年

VS2019では、スイッチをEnable project code有効にする必要があります(またはメニュー->デザイン->🗹プロジェクトコードの実行)。
marbel82

115

あなたはこのようなことをすることができます:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

30
このメソッドは、ViewModelをデザイナにとって使いやすくするためにも機能します(DependencyObjects自体ではないため)。
Pat

1
DependencyObjectには保護されたコンストラクタがinternal class MyDependencyObject : DependencyObject {}ありますnew MyDependencyObjectDependencyObject
Rico Suter


ビューモデルでこれを行う場合は、おそらくそれを静的クラスに抽象化して、結果を静的ブール値として保存する必要があります
Simon_Weaver

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

どこからでも使えます。これを使用して、データバインドされたビデオがデザイナーで再生されないようにします。


上記のバリエーションApplication.Current.MainWindow == nullですが、タイプテストの方がより直接的である方が好きです。また、Visual Studioでホストされているデザイナーがリソースを追加しているように見えるため、これを行う別の方法があります(Appコードをホストしているライブラリの特定の型にアクセスできない場合)((bool)Application.Current.Resources["ExpressionUseLayoutRounding"])。ただし、リソースがそこにないかどうかを確認する必要がありますが、デザイナーのコンテキストでは機能します。
ジョンライデグレン

9

Visual Studioが使用するコードを自動生成したとき

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

9

この関連する回答で述べたように、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

また、大規模なWPF / Silverlight / WP8 / WinRTアプリケーションにCaliburn.Microを広範囲に使用する場合、ビューモデルでも便利で汎用的な caliburnの静的プロパティを使用できます(Visual Studioと同じようにBlendでも機能します)。Execute.InDesignMode

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

私はこれを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利点は、特定のクラスの明示的な知識を必要とせず、コード全体でグローバルに使用できることです。具体的には、ビューモデルにダミーデータを入力します。


2

受け入れられた回答は私にとってはうまくいきませんでした(VS2019)。

何が起こっているのかを調べた後、私はこれを思いつきました:

    public static bool IsRunningInVisualStudioDesigner
    {
        get
        {
            // Are we looking at this dialog in the Visual Studio Designer or Blend?
            string appname = System.Reflection.Assembly.GetEntryAssembly().FullName;
            return appname.Contains("XDesProc");
        }
    }

これは、viewModel内からデザインタイムで実行していて、Windowsライブラリを使用できないかどうかを知る必要がある場合に役立ちました。私はそれが非常に少量のリフレクションであることを知っていますが、#if DEBUGそれが本番環境で実行されるとは思わなかったので、このコードをelse return false でラップしました。それをしない理由はありますか?
Toby Smith

1

あなたのクラスが空のコンストラクタを必要としないなら、私はあなたのためのアイデアを持っています。

空のコンストラクタを作成し、それを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>

上記のコードの結果

これは、何かに空のコンストラクタが本当に必要な場合は機能しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.