Quelles approches sont disponibles pour les données factices au moment de la conception dans WPF?

97

Je travaille sans mélange d'expression et j'utilise simplement l'éditeur XAML dans vs2010. La sagesse de ceci mis à part, je constate de plus en plus un besoin de liaison de données au moment du design. Pour les cas simples, la FallbackValuepropriété fonctionne très bien (Textboxes et TextBlocks, etc.). Mais surtout lorsqu'il s'agit de ItemsControlet autres, il faut vraiment que des exemples de données soient visibles dans le concepteur afin que vous puissiez ajuster et modifier les contrôles et les modèles de données sans avoir à exécuter l'exécutable.

Je sais que cela ObjectDataProviderpermet de se lier à un type et peut donc fournir des données au moment de la conception pour la visualisation, mais il y a ensuite un peu de jonglerie pour permettre aux données réelles d'exécution de se lier sans gaspiller de ressources en chargeant le chargement à la fois au moment de la conception, données factices et liaisons d'exécution.

Ce que je veux vraiment, c’est la possibilité d’afficher, par exemple, «John», «Paul», «George» et «Ringo» dans le concepteur XAML en tant qu’éléments stylables dans my ItemsControl, mais que des données réelles apparaissent lorsque l’application s'exécute.

Je sais également que Blend permet certains attributs sophistiqués qui définissent les données de liaison au moment de la conception qui sont effectivement ignorées par WPF dans les conditions d'exécution.

Donc mes questions sont:

1. Comment puis-je exploiter les liaisons au moment du design des collections et des données non triviales dans le concepteur XAML de Visual Studio, puis passer en douceur aux liaisons d'exécution?

2. Comment d'autres ont-ils résolu ce problème de données au moment de la conception par rapport à l'exécution? Dans mon cas, je ne peux pas très facilement utiliser les mêmes données pour les deux (comme on pourrait le faire avec, par exemple, une requête de base de données).

3. Existe-t-il des alternatives à l'expression blend que je pourrais utiliser pour la conception XAML intégrée aux données? (Je sais qu'il existe des alternatives, mais je veux spécifiquement quelque chose que je peux utiliser et voir des exemples de données liés, etc.?)

el2iot2
la source

Réponses:

120

À l'aide de VS2010, vous pouvez utiliser des attributs au moment du design (fonctionne à la fois pour SL et WPF). De toute façon, j'ai généralement une source de données fictive, donc c'est juste une question de:

  • Ajout de la déclaration d'espace de noms

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • Ajout du contexte de données fictives aux ressources de fenêtre / contrôle

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
  • Définition du contexte des données au moment du design

    <Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...

Fonctionne assez bien.

Goran
la source
2
Si vous rencontrez des problèmes lors de l'utilisation, d:DataContextvous pouvez trouver de l'aide dans cette question: stackoverflow.com/questions/8303803/…
Martin Liversage
27
Cet exemple ne provoquerait-il pas le chargement d'une instance de MockXViewModel dans vos ressources pour une version de version? N'est-ce pas un problème?
jpierson
12
FYI: Vous avez également besoin de ce qui suit, sinon le compilateur VS2012 ne compilera pas le fichier xaml: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"etmc:Ignorable="d"
Orion Edwards
51
jpierson a raison. Je préfère utiliser <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... De cette façon, le modèle de vue simulé ne sera créé que dans le concepteur, pas lors de l'exécution de votre application. Gardez à l'esprit que cette approche nécessite que votre modèle de vue fictive ait un constructeur sans paramètre. Mais il en va de même dans l'exemple donné ci-dessus dans la réponse.
René
2
@ René votre approche est bien meilleure. Veuillez l'ajouter comme réponse et je voterai pour cela
dss539
15

Comme un amalgame de la réponse acceptée de Goran et de l'excellent commentaire de René.

  • Ajoutez la déclaration d'espace de noms. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Référencez votre contexte de données de conception à partir du code.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...

John Stritenberger
la source
1
Je suis tenté de marquer cela comme la nouvelle réponse, mais peut-être pouvons-nous tirer le reste des détails.
el2iot2
Cela nécessite plus de visibilité, ou il doit être intégré à la réponse acceptée. C'est une bien meilleure solution.
Lauraducky
Pourquoi est-ce mieux? Au début, je pensais que la réponse acceptée produirait inutilement des modèles simulés également à l'exécution, mais j'ai testé cela et ce n'est pas le cas. Les ressources ne sont pas créées si elles ne sont pas utilisées.
Paul le
@Paul C'est vraiment une question de préférence, mais cette réponse conserve tout le contexte des données au moment de la conception dans une déclaration plutôt que de l'avoir à deux endroits.
Facilite les
1
@JohnStritenberger Ce n'est pas seulement une préférence, la réponse acceptée charge inutilement des ressources en mémoire pour toujours, pas seulement pour le concepteur.
UuDdLrLrSs
4

Karl Shifflett décrit une approche qui devrait fonctionner aussi bien pour VS2008 que VS2010:

Affichage des données au moment du design dans Visual Studio 2008 Cider Designer dans les projets WPF et Silverlight

Laurent Bugnion a une approche similaire qui se concentre sur Expression Blend. Cela pourrait fonctionner pour VS2010, mais je ne l'ai pas encore confirmé.

Simulation de données en mode conception dans Microsoft Expression Blend

dthrasher
la source
merci d'avoir porté ceci à mon attention. J'aime le concept DesignAndRunTimeDataContext.
el2iot2
1
Karl Shifflett a un article mis à jour pour Visual Studio 2010: exemples de données dans WPF et Silverlight Designer
totorocat
1
L'essentiel du contenu du lien devrait vraiment être édité dans la réponse, d'autant plus que le premier lien est maintenant mort.
Lauraducky
4

Peut-être que les nouvelles fonctionnalités de conception de Visual Studio 2010 et Expression Blend 4 sont une option pour vous.

Son fonctionnement est illustré dans l' exemple d'application BookLibrary de WPF Application Framework (WAF) . Veuillez télécharger la version .NET4.

jbe
la source
Merci pour le lien. Y a-t-il un fichier de code ou une construction particulier que je devrais examiner pour voir l'approche? (un bref aperçu serait génial)
el2iot2
Jetez un œil au projet BookLibrary.Presentation. Dans ce projet, vous trouverez le dossier "DesignData" qui est utilisé par les UserControls dans le dossier "Views".
jbe
1
+1. Je viens de jeter un œil à ça. Pour toute personne intéressée, l'exemple de modèle de vue de données est déclaré en XAML et référencé via d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD
4

J'utilise cette approche pour générer des données au moment du design avec .NET 4.5 et Visual Studio 2013.

Je n'ai qu'un seul ViewModel. Le modèle de vue a une propriété IsInDesignModequi indique si le mode de conception est actif ou non (voir la classe ViewModelBase). Ensuite, vous pouvez configurer vos données de conception (comme le remplissage d'un contrôle d'éléments) dans le constructeur de modèles de vue.

En outre, je ne chargerais pas de données réelles dans le constructeur de modèles de vue, cela peut entraîner des problèmes lors de l'exécution, mais la configuration des données pour la conception ne devrait pas être un problème.

public abstract class ViewModelBase
{
    public bool IsInDesignMode
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        }
    }
}

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel()
    {
        if (IsInDesignMode == true)
        {
            LoadDesignTimeData();
        }
    }

    private void LoadDesignTimeData()
    {
        // Load design time data here
    }       
}
Martin
la source
4

En utilisant Visual Studio 2017, j'ai essayé de suivre tous les guides et questions comme celui-ci et j'étais toujours confronté à un <ItemsControl>qui n'exécutait tout simplement pas le code que j'avais à l'intérieur du constructeur d'un DesignFooViewModelqui hérite de FooViewModel. J'ai confirmé la partie "n'a pas exécuté" en suivant ce guide MSDN "pratique" (spoiler: MessageBoxdébogage). Bien que cela ne soit pas directement lié à la question initiale, j'espère que cela fera gagner beaucoup de temps aux autres.

Il s'avère que je ne faisais rien de mal. Le problème était que mon application devait être construite pour x64. Comme Visual Studio est toujours en 2018 un processus 32 bits et ne peut apparemment pas faire tourner un processus hôte 64 bits pour la partie concepteur, il ne peut pas utiliser mes classes x64. Ce qui est vraiment grave, c'est qu'il n'y a aucune erreur à trouver dans aucun journal auquel je pourrais penser.

Donc, si vous tombez sur cette question parce que vous voyez de fausses données avec votre modèle de vue au moment de la conception (par exemple: <TextBlock Text="{Binding Name}"/>s'affiche, Namepeu importe que vous définissiez la propriété sur), la cause est probablement votre build x64. Si vous ne parvenez pas à modifier votre configuration de construction en anycpu ou x86 en raison de dépendances, envisagez de créer un nouveau projet qui est entièrement anycpu et qui n'a pas de dépendances (ou de dépendances). Ainsi, vous finissez par fractionner la plupart ou la totalité, sauf les parties d'initialisation du code de votre projet "WPF App" dans un projet de "bibliothèque de classes C #".

Pour la base de code sur laquelle je travaille, je pense que cela forcera une saine séparation des préoccupations au prix d'une duplication de code qui est probablement une chose positive nette.

joonas
la source
3

Similaire à la réponse la mieux notée, mais mieux à mon avis: vous pouvez créer une propriété statique pour renvoyer une instance de données de conception et la référencer directement à partir de XAML comme ceci:

<d:UserControl.DataContext>
    <Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>

Cela évite le besoin d'utiliser UserControl.Resources. Votre propriété statique peut fonctionner comme une fabrique vous permettant de construire des types de données non triviaux - par exemple, si vous n'avez pas de ctor par défaut, vous pouvez appeler une fabrique ou un conteneur ici pour injecter les dépendances appropriées.

Jack Ukleja
la source