web-dev-qa-db-fra.com

Existe-t-il un moyen de vérifier si WPF s'exécute actuellement en mode conception ou non?

Quelqu'un sait-il qu'il existe une variable d'état globale disponible pour que je puisse vérifier si le code est en cours d'exécution en mode conception (par exemple, dans Blend ou Visual Studio) ou non?

Cela ressemblerait à quelque chose comme ça:

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

La raison pour laquelle j'ai besoin de cela est la suivante: lorsque mon application est affichée en mode conception dans Expression Blend, je souhaite que ViewModel utilise à la place une "classe de client de conception" qui contient des données fictives que le concepteur peut afficher en mode création.

Cependant, lorsque l'application est en cours d'exécution, je souhaite bien sûr que le ViewModel utilise la classe Customer réelle qui renvoie des données réelles.

Actuellement, je résous ce problème en demandant au concepteur, avant qu'il ne travaille dessus, d'accéder au ViewModel et de remplacer "ApplicationDevelopmentMode.Executing" par "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);
        }
    }
}
136
Edward Tanguay

Je crois que vous recherchez GetIsInDesignMode , qui prend un DependencyObject.

C'est à dire.

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

Edit: Lorsque vous utilisez Silverlight/WP7, vous devez utiliser IsInDesignTool puisque GetIsInDesignMode peut renvoient parfois false dans Visual Studio:

DesignerProperties.IsInDesignTool

Edit: Et enfin, dans un souci de complétude, l'équivalent dans les applications WinRT/Metro/Windows Store est DesignModeEnabled :

Windows.ApplicationModel.DesignMode.DesignModeEnabled
214
Richard Szalay

Vous pouvez faire quelque chose comme ça:

DesignerProperties.GetIsInDesignMode(new DependencyObject());
107
Sacha Bruttin
public static bool InDesignMode()
{
    return !(Application.Current is App);
}

Fonctionne de n'importe où. Je l'utilise pour empêcher la lecture de vidéos de base de données dans le concepteur.

23
Patrick

Lorsque Visual Studio a généré du code pour moi, il a utilisé

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

Il existe d'autres moyens (peut-être plus récents) de spécifier des données de conception dans WPF, par exemple mentionné dans cette réponse .

Pour l'essentiel, vous pouvez spécifier des données de conception à l'aide d'un instance de conception de votre ViewModel :

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

ou par en spécifiant des exemples de données dans un fichier XAML :

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

Vous devez définir le SamplePage.xaml propriétés du fichier à:

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

Je les place dans ma balise UserControl, comme ceci:

<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="...">

Au moment de l'exécution, toutes les balises de conception "d:" disparaissent, de sorte que vous n'obtiendrez que votre contexte de données d'exécution, quelle que soit votre définition.

Modifier Vous pourriez aussi avoir besoin de ces lignes (je n'en suis pas certaine, mais elles semblent pertinentes):

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

Et si vous utilisez intensément Caliburn.Micro pour votre grand WPF/Silverlight/WP8/WinRT , vous pouvez utiliser un outil pratique et universel de caliburn Execute.InDesignMode propriété statique dans vos modèles de vue également (et cela fonctionne aussi bien dans Blend que dans 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"
        //};
    }
}
7
Sevenate

La réponse acceptée n'a pas fonctionné pour moi (VS2019).

Après avoir inspecté ce qui se passait, je trouvai ceci:

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

Je n'ai testé cela qu'avec Visual Studio 2013 et .NET 4.5, mais cela fait l'affaire.

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

Il est toutefois possible que certains paramètres de Visual Studio fassent passer cette valeur à false. Si cela se produit, nous pouvons simplement vérifier si ce nom de ressource existe. C'était null lorsque j'ai exécuté mon code en dehors du concepteur.

L'avantage de cette approche est qu'elle ne nécessite pas de connaissance explicite de la classe spécifique App et qu'elle peut être utilisée globalement dans tout votre code. Spécifiquement pour remplir les modèles de vue avec des données factices.

2
John Leidegren

J'ai une idée pour vous si votre classe n'a pas besoin d'un constructeur vide.

L'idée est de créer un constructeur vide, puis de le marquer avec ObsoleteAttribute. Le concepteur ignore l'attribut obsolète, mais le compilateur générera une erreur si vous essayez de l'utiliser, il n'y a donc aucun risque de l'utiliser accidentellement vous-même.

( pardonnez mon visuel de base )

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

Et le 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>

result of the above code

Cela ne fonctionnera pas si vraiment avez besoin du constructeur vide pour autre chose.

1
DonkeyMaster