WPF'nin şu anda tasarım modunda çalışıp çalışmadığını kontrol etmenin bir yolu var mı?


151

Kodun şu anda tasarım modunda (örn. Blend veya Visual Studio'da) çalışıp çalışmadığını kontrol edebilmem için kullanılabilen bazı global durum değişkenlerini bilen var mı?

Şöyle bir şeye benzeyecektir:

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

Buna ihtiyacımın nedeni şudur: Uygulamam Expression Blend'de tasarım modunda gösterilirken, ViewModel'in bunun yerine tasarımcının tasarım modunda görüntüleyebileceği sahte veriler içeren bir "Tasarım Müşteri sınıfı" kullanmasını istiyorum.

Bununla birlikte, uygulama gerçekten yürütülürken, tabii ki ViewModel'in gerçek verileri döndüren gerçek Müşteri sınıfını kullanmasını istiyorum.

Şu anda bunu, tasarımcının üzerinde çalışmadan önce ViewModel'e girmesini ve "ApplicationDevelopmentMode.Executing" i "ApplicationDevelopmentMode.Designing" olarak değiştirmesini sağlayarak çözüyorum:

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);
        }
    }
}

Yanıtlar:


233

DependencyObject alan GetIsInDesignMode'u aradığınıza inanıyorum .

Yani.

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

Düzenleme: Silverlight / WP7 kullanırken, kullanmalısınız IsInDesignToolberi GetIsInDesignModebazen Visual Studio sahte süre dönebilirsiniz:

DesignerProperties.IsInDesignTool

Düzenleme: Ve son olarak, eksiksizlik açısından WinRT / Metro / Windows Mağazası uygulamalarındaki eşdeğeri DesignModeEnabled:

Windows.ApplicationModel.DesignMode.DesignModeEnabled

3
Bir yan not olarak, IsInDesignMode aslında eklenmiş bir özelliktir, bu nedenle onu xaml'den bir bağlamada da kullanabilirsiniz. Yine de en yaygın kullanım
olmayabilir

3
Yanıtı WinRT ve WP gibi en son XAML "uygulamaları" ile güncel tuttuğunuz için teşekkür ederiz.
Sevenate

VS2019'da anahtar Enable project codeetkinleştirilmelidir (veya Menü-> Tasarım-> 🗹 Proje Kodunu Çalıştır).
marbel82

117

Bunun gibi bir şey yapabilirsiniz:

DesignerProperties.GetIsInDesignMode(new DependencyObject());

30
Bu yöntem aynı zamanda ViewModels'i tasarımcı dostu yapmak için de işe yarar (çünkü bunlar DependencyObjects olmadıklarından).
Pat

1
DependencyObject korumalı bir kurucuya sahip - bunun yerine tanımlayın internal class MyDependencyObject : DependencyObject {}ve kullanınnew MyDependencyObjectDependencyObject
Rico Suter


Bunu bir görünüm modelinde yapıyorsanız, muhtemelen onu statik bir sınıfa soyutlamak ve sonucu statik bir mantıksal olarak saklamak istersiniz
Simon_Weaver

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

Her yerden çalışır. Tasarımcıda veri bağlantılı videoların oynatılmasını durdurmak için kullanıyorum.


Application.Current.MainWindow == nullTip testini daha çok sevmeme rağmen , yukarıdakinin bir varyasyonu . Ayrıca, Visual Studio'da barındırılan tasarımcı kaynakları ekliyormuş gibi görünür, bu nedenle burada bunu yapmanın başka bir yolu vardır ( Appkodunuzu barındıran kitaplıkta belirli türe erişiminiz yoksa ) ((bool)Application.Current.Resources["ExpressionUseLayoutRounding"]). Kaynağın orada olup olmadığını kontrol etmeniz gerekiyor, ancak tasarımcı bağlamında çalışıyor.
John Leidegren

Bu cevap hiçbir yerde işe yaramıyor. Örneğin, bir kitaplıkta App sınıfına sahip değilsiniz. ;)
GregorMohorko

9

Visual Studio benim için otomatik olarak bazı kodlar oluşturduğunda kullanıldı

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

9

Bu ilgili cevapta belirtildiği gibi, WPF'de tasarım zamanı verilerini belirlemenin başka (belki daha yeni) yolları vardır .

Esasen, ViewModel'inizin tasarım zamanı örneğini kullanarak tasarım zamanı verilerini belirtebilirsiniz :

d:DataContext="{d:DesignInstance Type=v:MySampleData, IsDesignTimeCreatable=True}"

veya bir XAML dosyasında örnek verileri belirterek :

d:DataContext="{d:DesignData Source=../DesignData/SamplePage.xaml}">

SamplePage.xamlDosya özelliklerini şu şekilde ayarlamalısınız :

BuildAction:               DesignData
Copy to Output Directory:  Do not copy
Custom Tool:               [DELETE ANYTHING HERE SO THE FIELD IS EMPTY]

Bunları etiketime şu şekilde yerleştiriyorum 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="...">

Çalışma zamanında, tüm "d:" tasarım zamanı etiketleri kaybolur, bu nedenle yalnızca çalışma zamanı veri bağlamınızı alırsınız, ancak nasıl ayarlamayı seçerseniz seçin.

Düzenle Bu satırlara da ihtiyacınız olabilir (Emin değilim, ancak alakalı görünüyorlar):

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 

7

Ve büyük WPF / Silverlight / WP8 / WinRT uygulamanız için Caliburn.Micro'yu yoğun bir şekilde kullanıyorsanız, kullanışlı ve evrensel caliburn'un statik özelliğini görünüm modellerinde de kullanabilirsiniz (ve Blend'de Visual Studio'da olduğu kadar iyi çalışır):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

Bunu yalnızca Visual Studio 2013 ve .NET 4.5 ile test ettim ama hile yapıyor.

public static bool IsDesignerContext()
{
  var maybeExpressionUseLayoutRounding =
    Application.Current.Resources["ExpressionUseLayoutRounding"] as bool?;
  return maybeExpressionUseLayoutRounding ?? false;
}

Visual Studio'daki bazı ayarların bu değeri false olarak değiştirmesi mümkündür, bu olursa, yalnızca bu kaynak adının var olup olmadığını kontrol etmemizle sonuçlanabiliriz. O oldu nullben tasarımcı dışında kodumu çalıştırdığınızda.

Bu yaklaşımın iyi tarafı, belirli Appsınıf hakkında açık bilgi gerektirmemesi ve kodunuzun genelinde global olarak kullanılabilmesidir. Özellikle görünüm modellerini yapay verilerle doldurmak için.


2

Kabul edilen cevap benim için işe yaramadı (VS2019).

Neler olup bittiğini inceledikten sonra şunu buldum:

    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");
        }
    }

Bu, bir viewModel içinden tasarım zamanında çalışıp çalışmadığımı ve Windows kitaplıklarını kullanamadığımı bilmem gereken yerlerde benim için çalıştı. Bunun çok küçük bir yansıma miktarı olduğunu biliyorum ama üretimde çalışması fikrini beğenmedim, bu yüzden bu kodu #if DEBUGbaşka bir yanlış dönüşle sardım. Bunu yapmamak için herhangi bir sebep var mı?
Toby Smith

1

Sınıfınızın boş bir kurucuya ihtiyacı yoksa sizin için bir fikrim var.

Buradaki fikir, boş bir kurucu oluşturmak ve ardından bunu ObsoleteAttribute ile işaretlemektir. Tasarımcı eski özniteliği görmezden gelir, ancak kullanmaya çalışırsanız derleyici bir hata verir, bu nedenle yanlışlıkla kendi başınıza kullanma riski yoktur.

( görsel temelim için kusura bakmayın )

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

Ve 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>

yukarıdaki kodun sonucu

Başka bir şey için gerçekten boş kurucuya ihtiyacınız varsa, bu işe yaramaz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.