Quali approcci sono disponibili per i dati fittizi della fase di progettazione in WPF?


97

Sto lavorando senza miscela di espressioni e utilizzo solo l'editor XAML in vs2010. A parte questo, vedo sempre più la necessità di un data binding in fase di progettazione. Per casi semplici, la FallbackValueproprietà funziona molto bene (caselle di testo e blocchi di testo, ecc.). Ma soprattutto quando si ha a che fare con ItemsControle simili, è davvero necessario che i dati di esempio siano visibili nel designer in modo da poter regolare e modificare i controlli e i modelli di dati senza dover eseguire l'eseguibile.

So che ObjectDataProviderconsente l'associazione a un tipo e quindi può fornire dati in fase di progettazione per la visualizzazione, ma poi c'è un po 'di giocoleria per consentire ai dati di runtime reali di legarsi senza sprecare risorse caricando sia il tempo di progettazione, dati fittizi e binding di runtime.

In realtà quello che voglio è la possibilità di avere, ad esempio, "John", "Paul", "George" e "Ringo" vengono visualizzati nel designer XAML come elementi personalizzabili nel mio ItemsControl, ma i dati reali vengono visualizzati quando l'applicazione corre.

So anche che Blend consente alcuni attributi fantasiosi che definiscono i dati di associazione della fase di progettazione che vengono effettivamente ignorati da WPF in condizioni di runtime.

Quindi le mie domande sono:

1. Come posso sfruttare i collegamenti in fase di progettazione di raccolte e dati non banali nella finestra di progettazione XAML dello studio visivo e quindi passare facilmente ai collegamenti di runtime?

2. In che modo gli altri hanno risolto il problema dei dati in fase di progettazione rispetto a quelli di runtime? Nel mio caso, non posso usare molto facilmente gli stessi dati per entrambi (come si sarebbe in grado di fare, ad esempio, con una query di database).

3. Esistono alternative alla miscela di espressioni che potrei utilizzare per la progettazione XAML integrata nei dati? (So ​​che ci sono alcune alternative, ma voglio specificamente qualcosa che posso usare e vedere dati di esempio associati, ecc.)

Risposte:


120

Utilizzando VS2010 è possibile utilizzare gli attributi Design-Time (funziona sia per SL che per WPF). Di solito ho comunque una fonte di dati fittizia, quindi è solo questione di:

  • Aggiunta della dichiarazione dello spazio dei nomi

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • Aggiunta del contesto dati fittizio alla finestra / risorse di controllo

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
    
  • Impostazione del contesto dei dati in fase di progettazione

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

Funziona abbastanza bene.


2
Se si riscontrano problemi utilizzando d:DataContextpotreste trovare qualche aiuto in questa domanda: stackoverflow.com/questions/8303803/...
Martin Liversage

27
Questo esempio non causerebbe il caricamento di un'istanza di MockXViewModel nelle risorse per una build di rilascio? Non è questo un problema?
jpierson

12
FYI: Hai anche bisogno di quanto segue, o il compilatore VS2012 non compilerà il file xaml: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"emc:Ignorable="d"
Orion Edwards

51
jpierson ha ragione. Preferisco usare <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... In questo modo, il modello di visualizzazione deriso verrà creato solo nel designer, non durante l'esecuzione dell'applicazione. Tieni presente che questo approccio richiede che il tuo modello di visualizzazione fittizia abbia un costruttore senza parametri. Ma lo stesso è il caso nell'esempio fornito sopra nella risposta.
René

2
@ René il tuo approccio è decisamente migliore. Aggiungilo come risposta e lo voterò a favore
dss539

15

Come un amalgama della risposta accettata di Goran e dell'eccellente commento di René.

  • Aggiungi la dichiarazione dello spazio dei nomi. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Fare riferimento al contesto dei dati della fase di progettazione dal codice.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...


1
Sono tentato di contrassegnare questa come la nuova risposta, ma forse possiamo inserire il resto dei dettagli.
el2iot2

Ciò richiede maggiore visibilità o deve essere inserito nella risposta accettata. È una soluzione molto migliore.
Lauraducky

Perché è meglio? All'inizio pensavo che la risposta accettata avrebbe prodotto inutilmente modelli fittizi anche in runtime, ma l'ho testato e in effetti non lo fa. Le risorse non vengono create se non utilizzate.
Paul

@Paul È davvero una questione di preferenza, ma questa risposta mantiene l'intero contesto dei dati della fase di progettazione in una dichiarazione anziché averlo in due punti. Rende i cambiamenti più facili
John Stritenberger

1
@JohnStritenberger Non è solo una preferenza, la risposta accettata carica inutilmente le risorse in memoria per tutto il tempo, non solo per il progettista.
UuDdLrLrSs

4

Karl Shifflett descrive un approccio che dovrebbe funzionare altrettanto bene per VS2008 e VS2010:

Visualizzazione dei dati della fase di progettazione in Visual Studio 2008 Cider Designer nei progetti WPF e Silverlight

Laurent Bugnion ha un approccio simile che si concentra su Expression Blend. Si potrebbe lavorare per VS2010, ma non ho ancora confermato.

Simulazione dei dati in modalità progettazione in Microsoft Expression Blend


Grazie per avermelo fatto notare. Mi piace il concetto di DesignAndRunTimeDataContext.
el2iot2

1
Karl Shifflett ha un articolo aggiornato per Visual Studio 2010: Sample Data in the WPF e Silverlight Designer
totorocat

1
L'essenza del contenuto del collegamento dovrebbe davvero essere modificata nella risposta, soprattutto perché il primo collegamento è ora morto.
Lauraducky

4

Forse le nuove funzionalità in fase di progettazione di Visual Studio 2010 ed Expression Blend 4 sono un'opzione per te.

Il suo funzionamento è mostrato nell'applicazione di esempio BookLibrary di WPF Application Framework (WAF) . Scarica la versione .NET4.


Grazie per il collegamento. C'è un particolare file di codice o costrutto che dovrei esaminare per vedere l'approccio? (una breve panoramica sarebbe ottima)
el2iot2

Dai un'occhiata al progetto BookLibrary.Presentation. In questo progetto si trova la cartella "DesignData" utilizzata dagli UserControls nella cartella "Views".
jbe

1
+1. Ho appena dato un'occhiata a questo. Per chiunque sia interessato il modello di visualizzazione dati di esempio è dichiarato in XAML e referenziato tramite d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD

4

Uso questo approccio per generare dati in fase di progettazione con .NET 4.5 e Visual Studio 2013.

Ho solo un ViewModel. Il modello di visualizzazione ha una proprietà IsInDesignModeche dice se la modalità di progettazione è attiva o meno (vedi classe ViewModelBase). Quindi puoi impostare i dati della fase di progettazione (come il riempimento di un controllo degli elementi) nel costruttore dei modelli di visualizzazione.

Inoltre, non caricarei dati reali nel costruttore dei modelli di visualizzazione, ciò potrebbe portare a problemi in fase di runtime, ma l'impostazione dei dati per la fase di progettazione non dovrebbe essere un problema.

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

4

Utilizzando Visual Studio 2017 ho cercato di seguire tutte le guide e le domande come questa e stavo ancora affrontando un file <ItemsControl>che semplicemente non eseguiva il codice che avevo all'interno del costruttore di un DesignFooViewModelche eredita da FooViewModel. Ho confermato la parte "non eseguito" seguendo questa "pratica" guida MSDN (spoiler: MessageBoxdebugging). Anche se questo non è direttamente correlato alla domanda originale, spero che farà risparmiare agli altri molto tempo.

È venuto fuori che non stavo facendo niente di sbagliato. Il problema era che la mia applicazione doveva essere compilata per x64. Poiché Visual Studio è ancora nel 2018 un processo a 32 bit e apparentemente non può far girare un processo host a 64 bit per la parte designer, non può usare le mie classi x64. La cosa veramente brutta è che non ci sono errori da trovare in nessun registro a cui ho pensato.

Quindi, se ti imbatti in questa domanda perché stai vedendo dati fasulli con il tuo modello di visualizzazione della fase di progettazione (ad esempio: si <TextBlock Text="{Binding Name}"/>presenta Nameindipendentemente dalla proprietà su cui hai impostato) la causa è probabilmente la tua build x64. Se non sei in grado di modificare la configurazione della build in anycpu o x86 a causa delle dipendenze, prendi in considerazione la creazione di un nuovo progetto che sia completamente anycpu e non abbia le dipendenze (o eventuali dipendenze). Quindi si finisce per dividere la maggior parte o tutto tranne le parti di codice di inizializzazione dal progetto "App WPF" in un progetto "libreria di classi C #".

Per la base di codice su cui sto lavorando, penso che questo forzerà una sana separazione delle preoccupazioni al costo di una duplicazione del codice che è probabilmente una cosa netta positiva.


3

Simile alla risposta più votata, ma a mio avviso migliore: puoi creare una proprietà statica per restituire un'istanza dei dati di progettazione e farvi riferimento direttamente da XAML in questo modo:

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

Ciò evita la necessità di utilizzare UserControl.Resources. La tua proprietà statica può funzionare come una factory permettendoti di costruire tipi di dati non banali, ad esempio se non hai un ctor predefinito, puoi chiamare una factory o un container qui per iniettare le dipendenze appropriate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.